Tamar 0.7.2 → 0.7.3
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +19 -2
- data/Rakefile +5 -0
- data/Tamar.gemspec +27 -2
- data/VERSION +1 -1
- data/src/luadist/CMakeLists.txt +42 -0
- data/src/luadist/COPYRIGHT +34 -0
- data/src/luadist/README +95 -0
- data/src/luadist/dist.cmake +436 -0
- data/src/luadist/dist.info +20 -0
- data/src/luadist/dist/config.lua.in +108 -0
- data/src/luadist/dist/dep.lua +283 -0
- data/src/luadist/dist/fetch.lua +234 -0
- data/src/luadist/dist/init.lua +616 -0
- data/src/luadist/dist/log.lua +37 -0
- data/src/luadist/dist/manifest.lua +204 -0
- data/src/luadist/dist/package.lua +271 -0
- data/src/luadist/dist/persist.lua +132 -0
- data/src/luadist/dist/sys.lua +436 -0
- data/src/luadist/doc/index.html +147 -0
- data/src/luadist/doc/luadoc.css +286 -0
- data/src/luadist/doc/modules/dist.dep.html +489 -0
- data/src/luadist/doc/modules/dist.fetch.html +197 -0
- data/src/luadist/doc/modules/dist.html +547 -0
- data/src/luadist/doc/modules/dist.log.html +187 -0
- data/src/luadist/doc/modules/dist.manifest.html +235 -0
- data/src/luadist/doc/modules/dist.package.html +323 -0
- data/src/luadist/doc/modules/dist.persist.html +345 -0
- data/src/luadist/doc/modules/dist.sys.html +1058 -0
- data/src/luadist/luadist +443 -0
- metadata +27 -2
@@ -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
|