data-tar.lua /size: 7159 b    last modification: 2021-10-28 13:50
1if not modules then modules = { } end modules ['data-tar'] = {
2    version   = 1.001,
3    comment   = "companion to luat-lib.mkiv",
4    author    = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5    copyright = "PRAGMA ADE / ConTeXt Development Team",
6    license   = "see context related readme files"
7}
8
9local format, find, match = string.format, string.find, string.match
10
11local trace_locating = false  trackers.register("resolvers.locating", function(v) trace_locating = v end)
12
13local report_tar = logs.reporter("resolvers","tar")
14
15--[[ldx--
16<p>We use a url syntax for accessing the tar file itself and file in it:</p>
17
18<typing>
19tar:///oeps.tar?name=bla/bla.tex
20tar:///oeps.tar?tree=tex/texmf-local
21</typing>
22--ldx]]--
23
24local resolvers    = resolvers
25local findfile     = resolvers.findfile
26local registerfile = resolvers.registerfile
27local splitmethod  = resolvers.splitmethod
28local starttiming  = resolvers.starttiming
29local stoptiming   = resolvers.stoptiming
30
31local urlquery     = url.query
32
33--- hm, zip sits in the global namespace, but tar doesn't
34
35local tar          = utilities.tar or { }
36utilities.tar      = tar -- not needed
37
38local archives     = tar.archives or { }
39tar.archives       = archives
40
41local registeredfiles = tar.registeredfiles or { }
42tar.registeredfiles   = registeredfiles
43
44-- foo.tar.xz : done
45-- foo.tar.gz : todo
46-- foo.tar    : done
47
48local hashtar, fetchtar, wipetar  do
49
50    local suffix = file.suffix -- hassuffix .. no need to split
51
52    local tarfiles       = utilities.tar.file
53    local tarstrings     = utilities.tar.string
54
55    local hashtarfile    = tar.files.hash
56    local fetchtarfile   = tar.files.fetch
57
58    local hashtarstring  = tar.strings.hash
59    local fetchtarstring = tar.strings.fetch
60
61    local register       = resolvers.decompressors.register
62
63    hashtar = function(archive,strip)
64        local a = register(archive)
65        if a then
66            return hashtarstring(a,archive)
67        else
68            return hashtarfile(archive,archive)
69        end
70    end
71
72    fetchtar = function(archive,filename,list)
73        local a = register(archive)
74        if a then
75            return fetchtarstring(a,filename,list)
76        else
77            return fetchtarfile(archive,filename,list)
78        end
79    end
80
81    wipetar = resolvers.decompressors.unregister
82
83end
84
85local function validfile(archive,name)
86    return archive[name]
87end
88
89local function openarchive(name)
90    if not name or name == "" then
91        return nil
92    else
93        local arch = archives[name]
94        if not arch then
95           local full = findfile(name) or ""
96           arch = full ~= "" and hashtar(full,name) or false
97           archives[name] = arch
98        end
99        return arch
100    end
101end
102
103local function closearchive(name)
104    if not name or (name == "" and archives[name]) then
105        archives[name] = nil
106        wipetar(name)
107    end
108end
109
110tar.openarchive  = openarchive
111tar.closearchive = closearchive
112
113function resolvers.locators.tar(specification)
114    local archive = specification.filename
115    local tarfile = archive and archive ~= "" and openarchive(archive)
116    if trace_locating then
117        if tarfile then
118            report_tar("locator: archive %a found",archive)
119        else
120            report_tar("locator: archive %a not found",archive)
121        end
122    end
123end
124
125function resolvers.concatinators.tar(tarfile,path,name) -- ok ?
126    if not path or path == "" then
127        return format('%s?name=%s',tarfile,name)
128    else
129        return format('%s?name=%s/%s',tarfile,path,name)
130    end
131end
132
133local finders  = resolvers.finders
134local notfound = finders.notfound
135
136function finders.tar(specification)
137    local original = specification.original
138    local archive  = specification.filename
139    if archive then
140        local query     = urlquery(specification.query)
141        local queryname = query.name
142        if queryname then
143            local tfile = openarchive(archive)
144            if tfile then
145                if trace_locating then
146                    report_tar("finder: archive %a found",archive)
147                end
148                if validfile(tfile,queryname) then
149                    if trace_locating then
150                        report_tar("finder: file %a found",queryname)
151                    end
152                    return specification.original
153                elseif trace_locating then
154                    report_tar("finder: file %a not found",queryname)
155                end
156            elseif trace_locating then
157                report_tar("finder: unknown archive %a",archive)
158            end
159        end
160    end
161    if trace_locating then
162        report_tar("finder: %a not found",original)
163    end
164    return notfound()
165end
166
167local openers    = resolvers.openers
168local notfound   = openers.notfound
169local textopener = openers.helpers.textopener
170
171function openers.tar(specification)
172    local original = specification.original
173    local archive  = specification.filename
174    if archive then
175        local query     = urlquery(specification.query)
176        local queryname = query.name
177        if queryname then
178            local tfile = openarchive(archive)
179            if tfile then
180                if trace_locating then
181                    report_tar("opener; archive %a opened",archive)
182                end
183                local data = fetchtar(archive,queryname,tfile)
184                if data then
185                    if trace_locating then
186                        report_tar("opener: file %a found",queryname)
187                    end
188                    return textopener('tar',original,data) -- a string handle
189                elseif trace_locating then
190                    report_tar("opener: file %a not found",queryname)
191                end
192            elseif trace_locating then
193                report_tar("opener: unknown archive %a",archive)
194            end
195        end
196    end
197    if trace_locating then
198        report_tar("opener: %a not found",original)
199    end
200    return notfound()
201end
202
203loaders  = resolvers.loaders
204local notfound = loaders.notfound
205
206function loaders.tar(specification)
207    local original = specification.original
208    local archive  = specification.filename
209    if archive then
210        local query     = urlquery(specification.query)
211        local queryname = query.name
212        if queryname then
213            local tfile = openarchive(archive)
214            if tfile then
215                if trace_locating then
216                    report_tar("loader: archive %a opened",archive)
217                end
218                local data = fetchtar(archive,queryname,tfile)
219                if data then
220                    if trace_locating then
221                        report_tar("loader; file %a loaded",original)
222                    end
223                    return true, data, #data
224                elseif trace_locating then
225                    report_tar("loader: file %a not found",queryname)
226                end
227            elseif trace_locating then
228                report_tar("loader; unknown archive %a",archive)
229            end
230        end
231    end
232    if trace_locating then
233        report_tar("loader: %a not found",original)
234    end
235    return notfound()
236end
237