Tamar 0.7.2 → 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ --- This file is part of LuaDist project
2
+
3
+ name = "luadist"
4
+ version = "1.2"
5
+
6
+ desc = "Simple Lua Module Development, Distribution and Deployment Tool."
7
+ maintainer = "Peter Drahoš"
8
+ author = "Peter Drahoš, Peter Kapec, David Manura"
9
+ license = "MIT/X11"
10
+ url = "http://www.luadist.org"
11
+
12
+ depends = {
13
+ "lua ~> 5.1",
14
+ "md5 >= 1.1",
15
+ "luasocket >= 2.0.2",
16
+ "luafilesystem >= 1.4.1",
17
+ "luasec >= 0.4",
18
+ "unzip >= 6.0"
19
+ }
20
+
@@ -0,0 +1,108 @@
1
+ --- LuaDist configuration
2
+ -- The contents of this file is automaticaly generated.
3
+ -- Feel free to edit to suit your needs.
4
+
5
+ local write = io.write
6
+ local flush = io.flush
7
+ local getenv = os.getenv
8
+
9
+ -- Look for _PROGDIR by default
10
+ local path = _PROGDIR
11
+ if path then path = path:gsub("\\", "/") .. "/.." end
12
+
13
+ module ("dist.config")
14
+
15
+ -- LuaDist Install Identification
16
+ version = "@DIST_VERSION@" -- Current LuaDist version
17
+ arch = "@DIST_ARCH@" -- Host architecture
18
+ type = "@DIST_TYPE@" -- Host type
19
+
20
+ -- Behavior
21
+ binary = true -- Use binary dists.
22
+ source = true -- Use source dists (requires CMake and MinGW/gcc/VS to be installed).
23
+ test = false -- Run tests before install.
24
+ verbose = false -- Print verbose output.
25
+ debug = false -- Start debug mod. Will keep temporary directories too.
26
+ proxy = false -- HTTP proxy to use. False for none, otherwise the proxy address.
27
+ timeout = 10 -- HTTP fetch timeout (seconds)
28
+ cache = 5*60 -- Cache timeout (seconds)
29
+
30
+ --- Packages provided by host
31
+ -- If you install any packages manually or using your host OS installer you can add the name-version
32
+ -- here, LuaDist will NOT install these modules and will search for the libraries in the host
33
+ provides = {
34
+ -- "unzip-6.0" -- Is available on OSX and most Unix/Linux based installs.
35
+ }
36
+
37
+ -- Paths
38
+ root = path or getenv("DIST_ROOT") or "/"
39
+ temp = root .. "/tmp" -- Full path temp
40
+ log = temp .. "/luadist.log" -- Log file
41
+ dists = "share/luadist/dists"
42
+
43
+ -- URLs of repositories to search for dists. http:// or file:// URLs are cecognized atm.
44
+ repo = {
45
+ --- Examples
46
+ -- "file:///home/joe/my_dists" -- Private Local Repository Unix
47
+ -- "file://C:/MyDists" -- Private Local Repository Windows
48
+ -- "http://myserver.tld/repo" -- Private Online Repository
49
+
50
+ --- Use local repo to speed things up when re-deploying
51
+ -- "file://" .. root .. "/dist",
52
+
53
+ --- Official repo
54
+ "https://github.com/LuaDist/Repository/raw/master/"
55
+ }
56
+
57
+ --- !!! Do not edit below unless you know what you are doing. !!!
58
+ -- Additional CMake variables to pass to build
59
+ variables = {
60
+ --- Install defaults
61
+ INSTALL_BIN = "@INSTALL_BIN@",
62
+ INSTALL_LIB = "@INSTALL_LIB@",
63
+ INSTALL_INC = "@INSTALL_INC@",
64
+ INSTALL_ETC = "@INSTALL_ETC@",
65
+ INSTALL_LMOD = "@INSTALL_LMOD@",
66
+ INSTALL_CMOD = "@INSTALL_CMOD@",
67
+
68
+ --- LuaDist specific variables
69
+ DIST_VERSION = version,
70
+ DIST_ARCH = arch,
71
+ DIST_TYPE = type,
72
+
73
+ -- CMake specific setup
74
+ CMAKE_GENERATOR = "@CMAKE_GENERATOR@",
75
+ CMAKE_BUILD_TYPE = "@CMAKE_BUILD_TYPE@",
76
+
77
+ -- RPath functionality
78
+ CMAKE_SKIP_BUILD_RPATH = "@CMAKE_SKIP_BUILD_RPATH@",
79
+ CMAKE_BUILD_WITH_INSTALL_RPATH = "@CMAKE_BUILD_WITH_INSTALL_RPATH@",
80
+ CMAKE_INSTALL_RPATH = "@CMAKE_INSTALL_RPATH@",
81
+ CMAKE_INSTALL_RPATH_USE_LINK_PATH = "@CMAKE_INSTALL_RPATH_USE_LINK_PATH@",
82
+ CMAKE_INSTALL_NAME_DIR = "@CMAKE_INSTALL_NAME_DIR@",
83
+
84
+ -- OSX specific
85
+ CMAKE_OSX_ARCHITECTURES = "@CMAKE_OSX_ARCHITECTURES@",
86
+
87
+ }
88
+
89
+ -- Commands to use for building. (CMake 2.8+)
90
+ cmake = "cmake"
91
+ cmakeDebug = "cmake -DCMAKE_VERBOSE_MAKEFILE=true -DCMAKE_BUILD_TYPE=Debug"
92
+ ctest = "ctest"
93
+ ctestDebug = "ctest"
94
+ make = "cmake --build . --target install --clean-first"
95
+ makeDebug = "cmake --build . --target install --clean-first"
96
+
97
+ -- Add -j option to make in case of unix makefiles to speed up builds
98
+ if (variables.CMAKE_GENERATOR == "Unix Makefiles") then
99
+ make = make .. " -- -j6"
100
+ makeDebug = makeDebug .. " -- -j6"
101
+ end
102
+
103
+ -- Function used to display messages, warnings and errors
104
+ message = function(...)
105
+ write(...)
106
+ write("\n")
107
+ flush()
108
+ end
@@ -0,0 +1,283 @@
1
+ --- LuaDist dependency functions
2
+ -- Peter Drahoš, LuaDist Project, 2010
3
+ -- Original Code borrowed from LuaRocks Project
4
+
5
+ --- Dependency handling functions.
6
+ -- Dependencies are represented in LuaDist through strings with
7
+ -- a dist name followed by a comma-separated list of constraints.
8
+ -- Each constraint consists of an operator and a version number.
9
+ -- In this string format, version numbers are represented as
10
+ -- naturally as possible, like they are used by upstream projects
11
+ -- (e.g. "2.0beta3"). Internally, LuaDist converts them to a purely
12
+ -- numeric representation, allowing comparison following some
13
+ -- "common sense" heuristics. The precise specification of the
14
+ -- comparison criteria is the source code of this module, but the
15
+ -- test/test_deps.lua file included with LuaDist provides some
16
+ -- insights on what these criteria are.
17
+
18
+ module ("dist.dep", package.seeall)
19
+
20
+ local distr = require "dist"
21
+ local log = require "dist.log"
22
+ local manif = require "dist.manifest"
23
+
24
+ local operators = {
25
+ ["=="] = "==",
26
+ ["~="] = "~=",
27
+ [">"] = ">",
28
+ ["<"] = "<",
29
+ [">="] = ">=",
30
+ ["<="] = "<=",
31
+ ["~>"] = "~>",
32
+ -- plus some convenience translations
33
+ [""] = "==",
34
+ ["-"] = "==",
35
+ ["="] = "==",
36
+ ["!="] = "~="
37
+ }
38
+
39
+ local deltas = {
40
+ scm = -100,
41
+ rc = -1000,
42
+ pre = -10000,
43
+ beta = -100000,
44
+ alpha = -1000000,
45
+ work = -10000000,
46
+ }
47
+
48
+ local version_mt = {
49
+ --- Equality comparison for versions.
50
+ -- All version numbers must be equal.
51
+ -- If both versions have revision numbers, they must be equal;
52
+ -- otherwise the revision number is ignored.
53
+ -- @param v1 table: version table to compare.
54
+ -- @param v2 table: version table to compare.
55
+ -- @return boolean: true if they are considered equivalent.
56
+ __eq = function(v1, v2)
57
+ if #v1 ~= #v2 then
58
+ return false
59
+ end
60
+ for i = 1, #v1 do
61
+ if v1[i] ~= v2[i] then
62
+ return false
63
+ end
64
+ end
65
+ if v1.revision and v2.revision then
66
+ return (v1.revision == v2.revision)
67
+ end
68
+ return true
69
+ end,
70
+ --- Size comparison for versions.
71
+ -- All version numbers are compared.
72
+ -- If both versions have revision numbers, they are compared;
73
+ -- otherwise the revision number is ignored.
74
+ -- @param v1 table: version table to compare.
75
+ -- @param v2 table: version table to compare.
76
+ -- @return boolean: true if v1 is considered lower than v2.
77
+ __lt = function(v1, v2)
78
+ for i = 1, math.max(#v1, #v2) do
79
+ local v1i, v2i = v1[i] or 0, v2[i] or 0
80
+ if v1i ~= v2i then
81
+ return (v1i < v2i)
82
+ end
83
+ end
84
+ if v1.revision and v2.revision then
85
+ return (v1.revision < v2.revision)
86
+ end
87
+ return false
88
+ end
89
+ }
90
+
91
+ local version_cache = {}
92
+ setmetatable(version_cache, {
93
+ __mode = "kv"
94
+ })
95
+
96
+ --- Parse a version string, converting to table format.
97
+ -- A version table contains all components of the version string
98
+ -- converted to numeric format, stored in the array part of the table.
99
+ -- If the version contains a revision, it is stored numerically
100
+ -- in the 'revision' field. The original string representation of
101
+ -- the string is preserved in the 'string' field.
102
+ -- Returned version tables use a metatable
103
+ -- allowing later comparison through relational operators.
104
+ -- @param vstring string: A version number in string format.
105
+ -- @return table or nil: A version table or nil
106
+ -- if the input string contains invalid characters.
107
+ function parseVersion(vstring)
108
+ if not vstring then return nil end
109
+ assert(type(vstring) == "string")
110
+
111
+ local cached = version_cache[vstring]
112
+ if cached then
113
+ return cached
114
+ end
115
+
116
+ local version = {}
117
+ local i = 1
118
+
119
+ local function add_token(number)
120
+ version[i] = version[i] and version[i] + number/100000 or number
121
+ i = i + 1
122
+ end
123
+
124
+ -- trim leading and trailing spaces
125
+ vstring = vstring:match("^%s*(.*)%s*$")
126
+ version.string = vstring
127
+ -- store revision separately if any
128
+ local main, revision = vstring:match("(.*)%-(%d+)$")
129
+ if revision then
130
+ vstring = main
131
+ version.revision = tonumber(revision)
132
+ end
133
+ while #vstring > 0 do
134
+ -- extract a number
135
+ local token, rest = vstring:match("^(%d+)[%.%-%_]*(.*)")
136
+ if token then
137
+ add_token(tonumber(token))
138
+ else
139
+ -- extract a word
140
+ token, rest = vstring:match("^(%a+)[%.%-%_]*(.*)")
141
+ if not token then
142
+ return nil
143
+ end
144
+ local last = #version
145
+ version[i] = deltas[token] or (token:byte() / 1000)
146
+ end
147
+ vstring = rest
148
+ end
149
+ setmetatable(version, version_mt)
150
+ version_cache[vstring] = version
151
+ return version
152
+ end
153
+
154
+ --- Utility function to compare version numbers given as strings.
155
+ -- @param a string: one version.
156
+ -- @param b string: another version.
157
+ -- @return boolean: True if a > b.
158
+ function compareVersions(a, b)
159
+ return parseVersion(a) > parseVersion(b)
160
+ end
161
+
162
+ --- Consumes a constraint from a string, converting it to table format.
163
+ -- For example, a string ">= 1.0, > 2.0" is converted to a table in the
164
+ -- format {op = ">=", version={1,0}} and the rest, "> 2.0", is returned
165
+ -- back to the caller.
166
+ -- @param input string: A list of constraints in string format.
167
+ -- @return (table, string) or nil: A table representing the same
168
+ -- constraints and the string with the unused input, or nil if the
169
+ -- input string is invalid.
170
+ local function parseConstraint(input)
171
+ assert(type(input) == "string")
172
+
173
+ local op, version, rest = input:match("^([<>=~!]*)%s*([%w%.%_%-]+)[%s,]*(.*)")
174
+ op = operators[op]
175
+ version = parseVersion(version)
176
+ if not op or not version then return nil end
177
+ return { op = op, version = version }, rest
178
+ end
179
+
180
+ --- Convert a list of constraints from string to table format.
181
+ -- For example, a string ">= 1.0, < 2.0" is converted to a table in the format
182
+ -- {{op = ">=", version={1,0}}, {op = "<", version={2,0}}}.
183
+ -- Version tables use a metatable allowing later comparison through
184
+ -- relational operators.
185
+ -- @param input string: A list of constraints in string format.
186
+ -- @return table or nil: A table representing the same constraints,
187
+ -- or nil if the input string is invalid.
188
+ function parseConstraints(input)
189
+ assert(type(input) == "string")
190
+
191
+ local constraints, constraint = {}, nil
192
+ while #input > 0 do
193
+ constraint, input = parseConstraint(input)
194
+ if constraint then
195
+ table.insert(constraints, constraint)
196
+ else
197
+ return nil
198
+ end
199
+ end
200
+ return constraints
201
+ end
202
+
203
+ --- A more lenient check for equivalence between versions.
204
+ -- This returns true if the requested components of a version
205
+ -- match and ignore the ones that were not given. For example,
206
+ -- when requesting "2", then "2", "2.1", "2.3.5-9"... all match.
207
+ -- When requesting "2.1", then "2.1", "2.1.3" match, but "2.2"
208
+ -- doesn't.
209
+ -- @param version string or table: Version to be tested; may be
210
+ -- in string format or already parsed into a table.
211
+ -- @param requested string or table: Version requested; may be
212
+ -- in string format or already parsed into a table.
213
+ -- @return boolean: True if the tested version matches the requested
214
+ -- version, false otherwise.
215
+ local function partialMatch(version, requested)
216
+ assert(type(version) == "string" or type(version) == "table")
217
+ assert(type(requested) == "string" or type(version) == "table")
218
+
219
+ if type(version) ~= "table" then version = parseVersion(version) end
220
+ if type(requested) ~= "table" then requested = parseVersion(requested) end
221
+ if not version or not requested then return false end
222
+
223
+ for i = 1, #requested do
224
+ if requested[i] ~= version[i] then return false end
225
+ end
226
+ if requested.revision then
227
+ return requested.revision == version.revision
228
+ end
229
+ return true
230
+ end
231
+
232
+ --- Check if a version satisfies a set of constraints.
233
+ -- @param version table: A version in table format
234
+ -- @param constraints table: An array of constraints in table format.
235
+ -- @return boolean: True if version satisfies all constraints,
236
+ -- false otherwise.
237
+ function matchConstraints(version, constraints)
238
+ assert(type(version) == "table")
239
+ assert(type(constraints) == "table")
240
+ local ok = true
241
+ setmetatable(version, version_mt)
242
+ for _, constr in pairs(constraints) do
243
+ local constr_version = constr.version
244
+ setmetatable(constr.version, version_mt)
245
+ if constr.op == "==" then ok = version == constr_version
246
+ elseif constr.op == "~=" then ok = version ~= constr_version
247
+ elseif constr.op == ">" then ok = version > constr_version
248
+ elseif constr.op == "<" then ok = version < constr_version
249
+ elseif constr.op == ">=" then ok = version >= constr_version
250
+ elseif constr.op == "<=" then ok = version <= constr_version
251
+ elseif constr.op == "~>" then ok = partialMatch(version, constr_version)
252
+ end
253
+ if not ok then break end
254
+ end
255
+ return ok
256
+ end
257
+
258
+ --- Check if a version string is satisfied by a constraint string.
259
+ -- @param version string: A version in string format
260
+ -- @param constraints string: Constraints in string format.
261
+ -- @return boolean: True if version satisfies all constraints,
262
+ -- false otherwise.
263
+ function constrain(version, constraints)
264
+ local const = parseConstraints(constraints)
265
+ local ver = parseVersion(version)
266
+ if const and ver then
267
+ return matchConstraints(ver, const)
268
+ end
269
+ return nil, "Error parsing versions."
270
+ end
271
+
272
+ --- Split dist name into name and constraints.
273
+ -- @param name string: A string containing name and version constraints eg. "lua-5.1.4" or "luajit >= 1.0 < 2.0"
274
+ -- @return string, string: Returns separated name and constraints
275
+ function split(name)
276
+ local cut = string.find(name, "[%s-=<>~]+%d")
277
+ if cut then
278
+ -- Cut the string and remove - from version if needed.
279
+ return string.sub(name, 0, cut-1), string.gsub(string.sub(name, cut), "^[-%s]", "")
280
+ end
281
+ return name, nil
282
+ end
283
+
@@ -0,0 +1,234 @@
1
+ --- LuaDist URL fetch functions
2
+ -- Peter Drahoš, LuaDist Project, 2010
3
+
4
+ --- This module is responsible for downloading contents using URIs.
5
+ -- It should handle at least HTTP and FILE URIs as well as system paths transparently.
6
+ -- 2DO: support for more protocols if demanded.
7
+ -- Two functions are provided. Notice that http requests are cached.
8
+ -- download - To download dists.
9
+ -- get - To directly obtain manifests.
10
+
11
+ module ("dist.fetch", package.seeall)
12
+
13
+ local config = require "dist.config"
14
+ local sys = require "dist.sys"
15
+ local log = require "dist.log"
16
+
17
+ -- Download contents directly from HTTP source to file
18
+ local function downloadHTTP(src, file)
19
+ local ltn12 = require "ltn12"
20
+ local http = require "socket.http"
21
+
22
+ local request = {
23
+ url = src,
24
+ headers = {
25
+ USERAGENT = "LuaDist",
26
+ TIMEOUT = config.timeout,
27
+ },
28
+ sink = ltn12.sink.file(assert(io.open(file, "wb"))),
29
+ redirect = true,
30
+ }
31
+ if config.proxy then request.proxy = config.proxy end
32
+
33
+ local ok, err = http.request(request)
34
+ if not ok then return nil, "Failed to get contents of " .. src .. " error: " .. err end
35
+ return true
36
+ end
37
+
38
+ -- Download contents directly from HTTP source to file
39
+ local function downloadHTTPS(src, file)
40
+ local ltn12 = require "ltn12"
41
+ local https = require "ssl.https"
42
+
43
+ local request = {
44
+ url = src,
45
+ headers = {
46
+ USERAGENT = "LuaDist",
47
+ TIMEOUT = config.timeout,
48
+ },
49
+ protocol = "tlsv1",
50
+ options = "all",
51
+ verify = "none",
52
+ sink = ltn12.sink.file(assert(io.open(file, "wb"))),
53
+ }
54
+
55
+ local ok, err = https.request(request)
56
+ if not ok then return nil, "Failed to get contents of " .. src .. " error: " .. err end
57
+ return true
58
+ end
59
+
60
+ --- Fetch file from URI into destination.
61
+ -- @param src string: URI to fetch file from. Accepts paths too.
62
+ -- @param dest string: Destination dir, if not provided temporary dir will be used.
63
+ -- @return path, log: Path the file was downloaded and the resulting log message.
64
+ function download(src, dest)
65
+ assert(type(src) == "string", "fetch.download: Argument 'src' is not a string.")
66
+ assert(not dest or type(dest) == "string", "fecth.download: Argument 'dest' is not a string.")
67
+
68
+ -- Dont waste time
69
+ if src == dest then return true end
70
+
71
+ -- Make sure all paths are absolute and set
72
+ dest = sys.path(dest) or config.temp
73
+ src = sys.path(src)
74
+
75
+ -- Test destination existstence
76
+ local ok, err = sys.isDir(dest)
77
+ if not ok then return nil, "Destination " .. dest .. " is not a directory." end
78
+
79
+ -- Construct destination filename
80
+ local name = src:match("([^/]+)$")
81
+ dest = sys.path(dest, name)
82
+ part = dest .. ".part"
83
+
84
+ -- Test if the file is local
85
+ local file = sys.path((src:gsub("^file://","")))
86
+ if sys.isFile(file) then
87
+ local ok, err = sys.copy(file, dest)
88
+ if not ok then return nil, "Failed to coply local file " .. file .. " to " .. dest end
89
+ return dest, "Succesfuly copied " .. file .. " to " .. dest
90
+ elseif src:match("^file://") then
91
+ return nil, "Failed to get contents of " .. src .. " error: not found"
92
+ end -- else uncertain
93
+
94
+ -- Cache check
95
+ if config.cache then
96
+ local md5 = require "md5"
97
+ local lfs = require "lfs"
98
+
99
+ local path = sys.path(config.temp, "luadist_cache")
100
+ local cache = sys.path(path, md5.sumhexa(src))
101
+
102
+ if ((lfs.attributes(cache, "modification") or 0) + config.cache) > os.time() then
103
+ sys.copy(cache, dest)
104
+ return dest, "Retrieved from cache."
105
+ end
106
+ end
107
+
108
+ -- Depeding on the protocol try obtaining the source
109
+ local ok, err
110
+ if (src:match("http://")) then ok, err = downloadHTTP(src, part) end
111
+ if (src:match("https://")) then ok, err = downloadHTTPS(src, part) end
112
+
113
+ if not ok then return nil, err end
114
+ sys.move(part, dest)
115
+
116
+ -- Save cache
117
+ if config.cache then
118
+ local md5 = require "md5"
119
+
120
+ local path = sys.path(config.temp, "luadist_cache")
121
+ local cache = sys.path(path, md5.sumhexa(src))
122
+ sys.makeDir(path)
123
+ sys.copy(dest, cache)
124
+ end
125
+
126
+ if not ok then return nil, "Failed to get contents of " .. src .. " error: " .. err end
127
+ return dest, "Succesfuly downloaded " .. src .. " to " .. dest
128
+ end
129
+
130
+ -- Obtain contents directly from HTTP source
131
+ local function getHTTP(src)
132
+ local ltn12 = require "ltn12"
133
+ local http = require "socket.http"
134
+
135
+ local contents = {}
136
+ local request = {
137
+ url = src,
138
+ headers = {
139
+ USERAGENT = "LuaDist",
140
+ TIMEOUT = config.timeout,
141
+ },
142
+ sink = ltn12.sink.table(contents),
143
+ redirect = true,
144
+ }
145
+ if config.proxy then request.proxy = config.proxy end
146
+
147
+ local ok, err = http.request(request)
148
+ if not ok then return nil, "Failed to get contents of " .. src .. " error: " .. err end
149
+ return table.concat(contents)
150
+ end
151
+
152
+ -- Obtain contents directly from HTTP source
153
+ local function getHTTPS(src)
154
+ local ltn12 = require "ltn12"
155
+ local https = require "ssl.https"
156
+
157
+ local contents = {}
158
+ local request = {
159
+ url = src,
160
+ headers = {
161
+ USERAGENT = "LuaDist",
162
+ TIMEOUT = config.timeout,
163
+ },
164
+ protocol = "tlsv1",
165
+ options = "all",
166
+ verify = "none",
167
+ sink = ltn12.sink.table(contents),
168
+ }
169
+
170
+ local ok, err = https.request(request)
171
+
172
+ if not ok then return nil, "Failed to get contents of " .. src .. " error: " .. err end
173
+ return table.concat(contents)
174
+ end
175
+
176
+ --- Directly get file contents from URI using luasocket.
177
+ -- @param src string: URI to fetch file from. Accepts paths too.
178
+ -- @return text, log: Contents of the URL file or nil and log message.
179
+ function get(src)
180
+ assert(type(src) == "string", "fetch.get: Argument 'src' is not a string.")
181
+
182
+ -- Test if file is local
183
+ local file = sys.path((src:gsub("^file://","")))
184
+ if sys.isFile(file) then
185
+ local handle = io.open(file, "rb")
186
+ if not handle then return nil, "Failed to get contents of " .. file end
187
+ local ret = handle:read("*all")
188
+ handle:close()
189
+ return ret, "Succesfuly obtained contents of " .. file
190
+ elseif src:match("^file://") then
191
+ return nil, "Failed to get contents of " .. src .. " error: not found"
192
+ end -- else uncertain
193
+
194
+ -- Cache check
195
+ if config.cache then
196
+ local md5 = require "md5"
197
+ local lfs = require "lfs"
198
+
199
+ local path = sys.path(config.temp, "luadist_cache")
200
+ local cache = sys.path(path, md5.sumhexa(src))
201
+
202
+ if ((lfs.attributes(cache, "modification") or 0) + config.cache) > os.time() then
203
+ local file = io.open(cache, "rb")
204
+ if file then
205
+ local data = file:read("*all")
206
+ file:close()
207
+ return data, "Retrieved from cache."
208
+ end
209
+ end
210
+ end
211
+
212
+ -- Depeding on the protocol try obtaining the source
213
+ local data, err
214
+ if (src:match("http://")) then data, err = getHTTP(src) end
215
+ if (src:match("https://")) then data, err = getHTTPS(src) end
216
+
217
+ if (not data) then return nil, err end
218
+
219
+ -- Save cache
220
+ if config.cache then
221
+ local md5 = require "md5"
222
+
223
+ local path = sys.path(config.temp, "luadist_cache")
224
+ local cache = sys.path(path, md5.sumhexa(src))
225
+ sys.makeDir(path)
226
+ local file = io.open(cache, "wb")
227
+ if file then
228
+ file:write(data)
229
+ file:close()
230
+ end
231
+ end
232
+
233
+ return data, "Succesfuly obtained contents of " .. src
234
+ end