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.
- 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
|