Tamar 0.7.2 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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