summaryrefslogtreecommitdiff
path: root/tex/context/base/data-zip.lua
diff options
context:
space:
mode:
authorMarius <mariausol@gmail.com>2010-07-04 15:32:09 +0300
committerMarius <mariausol@gmail.com>2010-07-04 15:32:09 +0300
commit85b7bc695629926641c7cb752fd478adfdf374f3 (patch)
tree80293f5aaa7b95a500a78392c39688d8ee7a32fc /tex/context/base/data-zip.lua
downloadcontext-85b7bc695629926641c7cb752fd478adfdf374f3.tar.gz
stable 2010-05-24 13:10
Diffstat (limited to 'tex/context/base/data-zip.lua')
-rw-r--r--tex/context/base/data-zip.lua241
1 files changed, 241 insertions, 0 deletions
diff --git a/tex/context/base/data-zip.lua b/tex/context/base/data-zip.lua
new file mode 100644
index 000000000..aa3740a83
--- /dev/null
+++ b/tex/context/base/data-zip.lua
@@ -0,0 +1,241 @@
+if not modules then modules = { } end modules ['data-zip'] = {
+ 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 unpack = unpack or table.unpack
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+
+-- zip:///oeps.zip?name=bla/bla.tex
+-- zip:///oeps.zip?tree=tex/texmf-local
+-- zip:///texmf.zip?tree=/tex/texmf
+-- zip:///texmf.zip?tree=/tex/texmf-local
+-- zip:///texmf-mine.zip?tree=/tex/texmf-projects
+
+zip = zip or { }
+zip.archives = zip.archives or { }
+zip.registeredfiles = zip.registeredfiles or { }
+
+local finders, openers, loaders = resolvers.finders, resolvers.openers, resolvers.loaders
+local locators, hashers, concatinators = resolvers.locators, resolvers.hashers, resolvers.concatinators
+
+local archives = zip.archives
+
+local function validzip(str) -- todo: use url splitter
+ if not find(str,"^zip://") then
+ return "zip:///" .. str
+ else
+ return str
+ end
+end
+
+function zip.openarchive(name)
+ if not name or name == "" then
+ return nil
+ else
+ local arch = archives[name]
+ if not arch then
+ local full = resolvers.find_file(name) or ""
+ arch = (full ~= "" and zip.open(full)) or false
+ archives[name] = arch
+ end
+ return arch
+ end
+end
+
+function zip.closearchive(name)
+ if not name or (name == "" and archives[name]) then
+ zip.close(archives[name])
+ archives[name] = nil
+ end
+end
+
+function locators.zip(specification) -- where is this used? startup zips (untested)
+ specification = resolvers.splitmethod(specification)
+ local zipfile = specification.path
+ local zfile = zip.openarchive(name) -- tricky, could be in to be initialized tree
+ if trace_locating then
+ if zfile then
+ logs.report("fileio","zip locator, archive '%s' found",specification.original)
+ else
+ logs.report("fileio","zip locator, archive '%s' not found",specification.original)
+ end
+ end
+end
+
+function hashers.zip(tag,name)
+ if trace_locating then
+ logs.report("fileio","loading zip file '%s' as '%s'",name,tag)
+ end
+ resolvers.usezipfile(format("%s?tree=%s",tag,name))
+end
+
+function concatinators.zip(tag,path,name)
+ if not path or path == "" then
+ return format('%s?name=%s',tag,name)
+ else
+ return format('%s?name=%s/%s',tag,path,name)
+ end
+end
+
+function resolvers.isreadable.zip(name)
+ return true
+end
+
+function finders.zip(specification,filetype)
+ specification = resolvers.splitmethod(specification)
+ if specification.path then
+ local q = url.query(specification.query)
+ if q.name then
+ local zfile = zip.openarchive(specification.path)
+ if zfile then
+ if trace_locating then
+ logs.report("fileio","zip finder, archive '%s' found",specification.path)
+ end
+ local dfile = zfile:open(q.name)
+ if dfile then
+ dfile = zfile:close()
+ if trace_locating then
+ logs.report("fileio","zip finder, file '%s' found",q.name)
+ end
+ return specification.original
+ elseif trace_locating then
+ logs.report("fileio","zip finder, file '%s' not found",q.name)
+ end
+ elseif trace_locating then
+ logs.report("fileio","zip finder, unknown archive '%s'",specification.path)
+ end
+ end
+ end
+ if trace_locating then
+ logs.report("fileio","zip finder, '%s' not found",filename)
+ end
+ return unpack(finders.notfound)
+end
+
+function openers.zip(specification)
+ local zipspecification = resolvers.splitmethod(specification)
+ if zipspecification.path then
+ local q = url.query(zipspecification.query)
+ if q.name then
+ local zfile = zip.openarchive(zipspecification.path)
+ if zfile then
+ if trace_locating then
+ logs.report("fileio","zip opener, archive '%s' opened",zipspecification.path)
+ end
+ local dfile = zfile:open(q.name)
+ if dfile then
+ logs.show_open(specification)
+ if trace_locating then
+ logs.report("fileio","zip opener, file '%s' found",q.name)
+ end
+ return openers.text_opener(specification,dfile,'zip')
+ elseif trace_locating then
+ logs.report("fileio","zip opener, file '%s' not found",q.name)
+ end
+ elseif trace_locating then
+ logs.report("fileio","zip opener, unknown archive '%s'",zipspecification.path)
+ end
+ end
+ end
+ if trace_locating then
+ logs.report("fileio","zip opener, '%s' not found",filename)
+ end
+ return unpack(openers.notfound)
+end
+
+function loaders.zip(specification)
+ specification = resolvers.splitmethod(specification)
+ if specification.path then
+ local q = url.query(specification.query)
+ if q.name then
+ local zfile = zip.openarchive(specification.path)
+ if zfile then
+ if trace_locating then
+ logs.report("fileio","zip loader, archive '%s' opened",specification.path)
+ end
+ local dfile = zfile:open(q.name)
+ if dfile then
+ logs.show_load(filename)
+ if trace_locating then
+ logs.report("fileio","zip loader, file '%s' loaded",filename)
+ end
+ local s = dfile:read("*all")
+ dfile:close()
+ return true, s, #s
+ elseif trace_locating then
+ logs.report("fileio","zip loader, file '%s' not found",q.name)
+ end
+ elseif trace_locating then
+ logs.report("fileio","zip loader, unknown archive '%s'",specification.path)
+ end
+ end
+ end
+ if trace_locating then
+ logs.report("fileio","zip loader, '%s' not found",filename)
+ end
+ return unpack(openers.notfound)
+end
+
+-- zip:///somefile.zip
+-- zip:///somefile.zip?tree=texmf-local -> mount
+
+function resolvers.usezipfile(zipname)
+ zipname = validzip(zipname)
+ local specification = resolvers.splitmethod(zipname)
+ local zipfile = specification.path
+ if zipfile and not zip.registeredfiles[zipname] then
+ local tree = url.query(specification.query).tree or ""
+ local z = zip.openarchive(zipfile)
+ if z then
+ local instance = resolvers.instance
+ if trace_locating then
+ logs.report("fileio","zip registering, registering archive '%s'",zipname)
+ end
+ statistics.starttiming(instance)
+ resolvers.prepend_hash('zip',zipname,zipfile)
+ resolvers.extend_texmf_var(zipname) -- resets hashes too
+ zip.registeredfiles[zipname] = z
+ instance.files[zipname] = resolvers.register_zip_file(z,tree or "")
+ statistics.stoptiming(instance)
+ elseif trace_locating then
+ logs.report("fileio","zip registering, unknown archive '%s'",zipname)
+ end
+ elseif trace_locating then
+ logs.report("fileio","zip registering, '%s' not found",zipname)
+ end
+end
+
+function resolvers.register_zip_file(z,tree)
+ local files, filter = { }, ""
+ if tree == "" then
+ filter = "^(.+)/(.-)$"
+ else
+ filter = format("^%s/(.+)/(.-)$",tree)
+ end
+ if trace_locating then
+ logs.report("fileio","zip registering, using filter '%s'",filter)
+ end
+ local register, n = resolvers.register_file, 0
+ for i in z:files() do
+ local path, name = match(i.filename,filter)
+ if path then
+ if name and name ~= '' then
+ register(files, name, path)
+ n = n + 1
+ else
+ -- directory
+ end
+ else
+ register(files, i.filename, '')
+ n = n + 1
+ end
+ end
+ logs.report("fileio","zip registering, %s files registered",n)
+ return files
+end