diff options
author | V1K1NGbg <victor@ilchev.com> | 2024-08-06 21:21:35 +0300 |
---|---|---|
committer | V1K1NGbg <victor@ilchev.com> | 2024-08-06 21:21:35 +0300 |
commit | bd2e8c62298d85816faed12604363c2240a49dee (patch) | |
tree | 1e7b1733ff317bd91ec044d6efed77629be36172 | |
parent | 2b553013c302a84a8f76ca093fda89e6f4e54432 (diff) | |
download | luarocks-bd2e8c62298d85816faed12604363c2240a49dee.tar.gz luarocks-bd2e8c62298d85816faed12604363c2240a49dee.tar.bz2 luarocks-bd2e8c62298d85816faed12604363c2240a49dee.zip |
rockspec
-rw-r--r-- | src/luarocks/core/types/rockspec.tl (renamed from src/luarocks/core/types/rockspec.d.tl) | 0 | ||||
-rw-r--r-- | src/luarocks/deps-incomplete.lua (renamed from src/luarocks/deps-original.lua) | 427 | ||||
-rw-r--r-- | src/luarocks/deps.lua | 427 | ||||
-rw-r--r-- | src/luarocks/deps.tl | 2 | ||||
-rw-r--r-- | src/luarocks/rockspecs-original.lua | 183 | ||||
-rw-r--r-- | src/luarocks/rockspecs.lua | 131 | ||||
-rw-r--r-- | src/luarocks/rockspecs.tl | 10 |
7 files changed, 691 insertions, 489 deletions
diff --git a/src/luarocks/core/types/rockspec.d.tl b/src/luarocks/core/types/rockspec.tl index b9ed54de..b9ed54de 100644 --- a/src/luarocks/core/types/rockspec.d.tl +++ b/src/luarocks/core/types/rockspec.tl | |||
diff --git a/src/luarocks/deps-original.lua b/src/luarocks/deps-incomplete.lua index 1a9eefde..df2fbbd5 100644 --- a/src/luarocks/deps-original.lua +++ b/src/luarocks/deps-incomplete.lua | |||
@@ -1,7 +1,8 @@ | |||
1 | local _tl_compat; if (tonumber((_VERSION or ''):match('[%d.]*$')) or 0) < 5.3 then local p, m = pcall(require, 'compat53.module'); if p then _tl_compat = m end end; local assert = _tl_compat and _tl_compat.assert or assert; local io = _tl_compat and _tl_compat.io or io; local ipairs = _tl_compat and _tl_compat.ipairs or ipairs; local pairs = _tl_compat and _tl_compat.pairs or pairs; local string = _tl_compat and _tl_compat.string or string; local table = _tl_compat and _tl_compat.table or table | ||
1 | 2 | ||
2 | --- High-level dependency related functions. | ||
3 | local deps = {} | 3 | local deps = {} |
4 | 4 | ||
5 | |||
5 | local cfg = require("luarocks.core.cfg") | 6 | local cfg = require("luarocks.core.cfg") |
6 | local manif = require("luarocks.manif") | 7 | local manif = require("luarocks.manif") |
7 | local path = require("luarocks.path") | 8 | local path = require("luarocks.path") |
@@ -12,34 +13,55 @@ local vers = require("luarocks.core.vers") | |||
12 | local queries = require("luarocks.queries") | 13 | local queries = require("luarocks.queries") |
13 | local deplocks = require("luarocks.deplocks") | 14 | local deplocks = require("luarocks.deplocks") |
14 | 15 | ||
15 | --- Generate a function that matches dep queries against the manifest, | 16 | |
16 | -- taking into account rocks_provided, the list of versions to skip, | 17 | |
17 | -- and the lockfile. | 18 | |
18 | -- @param deps_mode "one", "none", "all" or "order" | 19 | |
19 | -- @param rocks_provided a one-level table mapping names to versions, | 20 | |
20 | -- listing rocks to consider provided by the VM | 21 | |
21 | -- @param rocks_provided table: A table of auto-provided dependencies. | 22 | |
22 | -- by this Lua implementation for the given dependency. | 23 | |
23 | -- @param depskey key to use when matching the lockfile ("dependencies", | 24 | |
24 | -- "build_dependencies", etc.) | 25 | |
25 | -- @param skip_set a two-level table mapping names to versions to | 26 | |
26 | -- boolean, listing rocks that should not be matched | 27 | |
27 | -- @return function(dep): {string}, {string:string}, string, boolean | 28 | |
28 | -- * array of matching versions | 29 | |
29 | -- * map of versions to locations | 30 | |
30 | -- * version matched via lockfile if any | 31 | |
31 | -- * true if rock matched via rocks_provided | 32 | |
33 | |||
34 | |||
35 | |||
36 | |||
37 | |||
38 | |||
39 | |||
40 | |||
41 | |||
42 | |||
43 | |||
44 | |||
45 | |||
46 | |||
47 | |||
48 | |||
49 | |||
50 | |||
51 | |||
52 | |||
53 | |||
54 | |||
55 | |||
56 | |||
57 | |||
32 | local function prepare_get_versions(deps_mode, rocks_provided, depskey, skip_set) | 58 | local function prepare_get_versions(deps_mode, rocks_provided, depskey, skip_set) |
33 | assert(type(deps_mode) == "string") | ||
34 | assert(type(rocks_provided) == "table") | ||
35 | assert(type(depskey) == "string") | ||
36 | assert(type(skip_set) == "table" or skip_set == nil) | ||
37 | 59 | ||
38 | return function(dep) | 60 | return function(dep) |
39 | local versions, locations | 61 | local versions, locations |
40 | local provided = rocks_provided[dep.name] | 62 | local provided = rocks_provided[dep.name] |
41 | if provided then | 63 | if provided then |
42 | -- Provided rocks have higher priority than manifest's rocks. | 64 | |
43 | versions, locations = { provided }, {} | 65 | versions, locations = { provided }, {} |
44 | else | 66 | else |
45 | if deps_mode == "none" then | 67 | if deps_mode == "none" then |
@@ -63,21 +85,20 @@ local function prepare_get_versions(deps_mode, rocks_provided, depskey, skip_set | |||
63 | end | 85 | end |
64 | end | 86 | end |
65 | 87 | ||
66 | --- Attempt to match a dependency to an installed rock. | 88 | |
67 | -- @param get_versions a getter function obtained via prepare_get_versions | 89 | |
68 | -- @return (string, string, table) or (nil, nil, table): | 90 | |
69 | -- 1. latest installed version of the rock matching the dependency | 91 | |
70 | -- 2. location where the installed version is installed | 92 | |
71 | -- 3. the 'dep' query table | 93 | |
72 | -- 4. true if provided via VM | 94 | |
73 | -- or | 95 | |
74 | -- 1. nil | 96 | |
75 | -- 2. nil | 97 | |
76 | -- 3. either 'dep' or an alternative query to be used | 98 | |
77 | -- 4. false | 99 | |
78 | local function match_dep(dep, get_versions) | 100 | local function match_dep(dep, |
79 | assert(type(dep) == "table") | 101 | get_versions) |
80 | assert(type(get_versions) == "function") | ||
81 | 102 | ||
82 | local versions, locations, lockversion, provided = get_versions(dep) | 103 | local versions, locations, lockversion, provided = get_versions(dep) |
83 | 104 | ||
@@ -105,9 +126,8 @@ local function match_dep(dep, get_versions) | |||
105 | return latest_vstring, locations[latest_vstring], dep, provided | 126 | return latest_vstring, locations[latest_vstring], dep, provided |
106 | end | 127 | end |
107 | 128 | ||
108 | local function match_all_deps(dependencies, get_versions) | 129 | local function match_all_deps(dependencies, |
109 | assert(type(dependencies) == "table") | 130 | get_versions) |
110 | assert(type(get_versions) == "function") | ||
111 | 131 | ||
112 | local matched, missing, no_upgrade = {}, {}, {} | 132 | local matched, missing, no_upgrade = {}, {}, {} |
113 | 133 | ||
@@ -116,7 +136,7 @@ local function match_all_deps(dependencies, get_versions) | |||
116 | found, _, dep, provided = match_dep(dep, get_versions) | 136 | found, _, dep, provided = match_dep(dep, get_versions) |
117 | if found then | 137 | if found then |
118 | if not provided then | 138 | if not provided then |
119 | matched[dep] = {name = dep.name, version = found} | 139 | matched[dep] = { name = dep.name, version = found } |
120 | end | 140 | end |
121 | else | 141 | else |
122 | if dep.constraints[1] and dep.constraints[1].no_upgrade then | 142 | if dep.constraints[1] and dep.constraints[1].no_upgrade then |
@@ -129,53 +149,41 @@ local function match_all_deps(dependencies, get_versions) | |||
129 | return matched, missing, no_upgrade | 149 | return matched, missing, no_upgrade |
130 | end | 150 | end |
131 | 151 | ||
132 | --- Attempt to match dependencies of a rockspec to installed rocks. | 152 | |
133 | -- @param dependencies table: The table of dependencies. | 153 | |
134 | -- @param rocks_provided table: The table of auto-provided dependencies. | 154 | |
135 | -- @param skip_set table or nil: Program versions to not use as valid matches. | 155 | |
136 | -- Table where keys are program names and values are tables where keys | 156 | |
137 | -- are program versions and values are 'true'. | 157 | |
138 | -- @param deps_mode string: Which trees to check dependencies for | 158 | |
139 | -- @return table, table, table: A table where keys are dependencies parsed | 159 | |
140 | -- in table format and values are tables containing fields 'name' and | 160 | |
141 | -- version' representing matches; a table of missing dependencies | 161 | |
142 | -- parsed as tables; and a table of "no-upgrade" missing dependencies | 162 | |
143 | -- (to be used in plugin modules so that a plugin does not force upgrade of | 163 | |
144 | -- its parent application). | 164 | |
145 | function deps.match_deps(dependencies, rocks_provided, deps_mode, skip_set) | 165 | function deps.match_deps(dependencies, rocks_provided, deps_mode, skip_set) |
146 | assert(type(dependencies) == "table") | ||
147 | assert(type(rocks_provided) == "table") | ||
148 | assert(type(skip_set) == "table" or skip_set == nil) | ||
149 | assert(type(deps_mode) == "string") | ||
150 | 166 | ||
151 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, "dependencies", skip_set) | 167 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, "dependencies", skip_set) |
152 | return match_all_deps(dependencies, get_versions) | 168 | return match_all_deps(dependencies, get_versions) |
153 | end | 169 | end |
154 | 170 | ||
155 | local function rock_status(dep, get_versions) | 171 | local function rock_status(dep, get_versions) |
156 | assert(dep:type() == "query") | ||
157 | assert(type(get_versions) == "function") | ||
158 | |||
159 | local installed, _, _, provided = match_dep(dep, get_versions) | 172 | local installed, _, _, provided = match_dep(dep, get_versions) |
160 | local installation_type = provided and "provided by VM" or "installed" | 173 | local installation_type = provided and "provided by VM" or "installed" |
161 | return installed and installed.." "..installation_type..": success" or "not installed" | 174 | return installed and installed .. " " .. installation_type .. ": success" or "not installed" |
162 | end | 175 | end |
163 | 176 | ||
164 | --- Check depenendencies of a package and report any missing ones. | 177 | |
165 | -- @param name string: package name. | 178 | |
166 | -- @param version string: package version. | 179 | |
167 | -- @param dependencies table: array of dependencies. | 180 | |
168 | -- @param deps_mode string: Which trees to check dependencies for | 181 | |
169 | -- @param rocks_provided table: A table of auto-dependencies provided | 182 | |
170 | -- by this Lua implementation for the given dependency. | 183 | |
171 | -- "one" for the current default tree, "all" for all trees, | 184 | |
172 | -- "order" for all trees with priority >= the current default, "none" for no trees. | 185 | |
173 | function deps.report_missing_dependencies(name, version, dependencies, deps_mode, rocks_provided) | 186 | function deps.report_missing_dependencies(name, version, dependencies, deps_mode, rocks_provided) |
174 | assert(type(name) == "string") | ||
175 | assert(type(version) == "string") | ||
176 | assert(type(dependencies) == "table") | ||
177 | assert(type(deps_mode) == "string") | ||
178 | assert(type(rocks_provided) == "table") | ||
179 | 187 | ||
180 | if deps_mode == "none" then | 188 | if deps_mode == "none" then |
181 | return | 189 | return |
@@ -200,11 +208,6 @@ function deps.report_missing_dependencies(name, version, dependencies, deps_mode | |||
200 | end | 208 | end |
201 | 209 | ||
202 | function deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey) | 210 | function deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey) |
203 | assert(dep:type() == "query") | ||
204 | assert(type(deps_mode) == "string" or deps_mode == nil) | ||
205 | assert(type(rocks_provided) == "table" or rocks_provided == nil) | ||
206 | assert(type(verify) == "boolean" or verify == nil) | ||
207 | assert(type(depskey) == "string") | ||
208 | 211 | ||
209 | deps_mode = deps_mode or "all" | 212 | deps_mode = deps_mode or "all" |
210 | rocks_provided = rocks_provided or {} | 213 | rocks_provided = rocks_provided or {} |
@@ -224,9 +227,9 @@ function deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey | |||
224 | 227 | ||
225 | local url, search_err = search.find_suitable_rock(dep) | 228 | local url, search_err = search.find_suitable_rock(dep) |
226 | if not url then | 229 | if not url then |
227 | return nil, "Could not satisfy dependency "..tostring(dep)..": "..search_err | 230 | return nil, "Could not satisfy dependency " .. tostring(dep) .. ": " .. search_err |
228 | end | 231 | end |
229 | util.printout("Installing "..url) | 232 | util.printout("Installing " .. url) |
230 | local install_args = { | 233 | local install_args = { |
231 | rock = url, | 234 | rock = url, |
232 | deps_mode = deps_mode, | 235 | deps_mode = deps_mode, |
@@ -235,7 +238,7 @@ function deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey | |||
235 | } | 238 | } |
236 | local ok, install_err, errcode = install.command(install_args) | 239 | local ok, install_err, errcode = install.command(install_args) |
237 | if not ok then | 240 | if not ok then |
238 | return nil, "Failed installing dependency: "..url.." - "..install_err, errcode | 241 | return nil, "Failed installing dependency: " .. url .. " - " .. install_err, errcode |
239 | end | 242 | end |
240 | 243 | ||
241 | found, where = match_dep(dep, get_versions) | 244 | found, where = match_dep(dep, get_versions) |
@@ -246,15 +249,15 @@ function deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey | |||
246 | end | 249 | end |
247 | 250 | ||
248 | local function check_supported_platforms(rockspec) | 251 | local function check_supported_platforms(rockspec) |
249 | if rockspec.supported_platforms and next(rockspec.supported_platforms) then | 252 | if rockspec.supported_platforms and next(rockspec.supported_platforms) ~= nil then |
250 | local all_negative = true | 253 | local all_negative = true |
251 | local supported = false | 254 | local supported = false |
252 | for _, plat in pairs(rockspec.supported_platforms) do | 255 | for _, plat in ipairs(rockspec.supported_platforms) do |
253 | local neg | 256 | local neg |
254 | neg, plat = plat:match("^(!?)(.*)") | 257 | neg, plat = plat:match("^(!?)(.*)") |
255 | if neg == "!" then | 258 | if neg == "!" then |
256 | if cfg.is_platform(plat) then | 259 | if cfg.is_platform(plat) then |
257 | return nil, "This rockspec for "..rockspec.package.." does not support "..plat.." platforms." | 260 | return nil, "This rockspec for " .. rockspec.package .. " does not support " .. plat .. " platforms." |
258 | end | 261 | end |
259 | else | 262 | else |
260 | all_negative = false | 263 | all_negative = false |
@@ -266,32 +269,26 @@ local function check_supported_platforms(rockspec) | |||
266 | end | 269 | end |
267 | if supported == false and not all_negative then | 270 | if supported == false and not all_negative then |
268 | local plats = cfg.print_platforms() | 271 | local plats = cfg.print_platforms() |
269 | return nil, "This rockspec for "..rockspec.package.." does not support "..plats.." platforms." | 272 | return nil, "This rockspec for " .. rockspec.package .. " does not support " .. plats .. " platforms." |
270 | end | 273 | end |
271 | end | 274 | end |
272 | 275 | ||
273 | return true | 276 | return true |
274 | end | 277 | end |
275 | 278 | ||
276 | --- Check dependencies of a rock and attempt to install any missing ones. | ||
277 | -- Packages are installed using the LuaRocks "install" command. | ||
278 | -- Aborts the program if a dependency could not be fulfilled. | ||
279 | -- @param rockspec table: A rockspec in table format. | ||
280 | -- @param depskey string: Rockspec key to fetch to get dependency table | ||
281 | -- ("dependencies", "build_dependencies", etc.). | ||
282 | -- @param deps_mode string | ||
283 | -- @param verify boolean | ||
284 | -- @param deplock_dir string: dirname of the deplock file | ||
285 | -- @return boolean or (nil, string, [string]): True if no errors occurred, or | ||
286 | -- nil and an error message if any test failed, followed by an optional | ||
287 | -- error code. | ||
288 | function deps.fulfill_dependencies(rockspec, depskey, deps_mode, verify, deplock_dir) | ||
289 | assert(type(rockspec) == "table") | ||
290 | assert(type(depskey) == "string") | ||
291 | assert(type(deps_mode) == "string") | ||
292 | assert(type(verify) == "boolean" or verify == nil) | ||
293 | assert(type(deplock_dir) == "string" or deplock_dir == nil) | ||
294 | 279 | ||
280 | |||
281 | |||
282 | |||
283 | |||
284 | |||
285 | |||
286 | |||
287 | |||
288 | |||
289 | |||
290 | |||
291 | function deps.fulfill_dependencies(rockspec, depskey, deps_mode, verify, deplock_dir) | ||
295 | local name = rockspec.name | 292 | local name = rockspec.name |
296 | local version = rockspec.version | 293 | local version = rockspec.version |
297 | local rocks_provided = rockspec.rocks_provided | 294 | local rocks_provided = rockspec.rocks_provided |
@@ -301,16 +298,23 @@ function deps.fulfill_dependencies(rockspec, depskey, deps_mode, verify, deplock | |||
301 | util.printout("Using dependencies pinned in lockfile: " .. filename) | 298 | util.printout("Using dependencies pinned in lockfile: " .. filename) |
302 | 299 | ||
303 | local get_versions = prepare_get_versions("none", rocks_provided, depskey) | 300 | local get_versions = prepare_get_versions("none", rocks_provided, depskey) |
301 | local dnsnamestr, dversionstr | ||
304 | for dnsname, dversion in deplocks.each(depskey) do | 302 | for dnsname, dversion in deplocks.each(depskey) do |
305 | local dname, dnamespace = util.split_namespace(dnsname) | 303 | if type(dnsname) == "string" then |
306 | local dep = queries.new(dname, dnamespace, dversion) | 304 | dnsnamestr = dnsname |
305 | end | ||
306 | if type(dversion) == "string" then | ||
307 | dversionstr = dversion | ||
308 | end | ||
309 | local dname, dnamespace = util.split_namespace(dnsnamestr) | ||
310 | local dep = queries.new(dname, dnamespace, dversionstr) | ||
307 | 311 | ||
308 | util.printout(("%s %s is pinned to %s (%s)"):format( | 312 | util.printout(("%s %s is pinned to %s (%s)"):format( |
309 | name, version, tostring(dep), rock_status(dep, get_versions))) | 313 | name, version, tostring(dep), rock_status(dep, get_versions))) |
310 | 314 | ||
311 | local ok, err = deps.fulfill_dependency(dep, "none", rocks_provided, verify, depskey) | 315 | local okfullfill, errfullfill = deps.fulfill_dependency(dep, "none", rocks_provided, verify, depskey) |
312 | if not ok then | 316 | if not okfullfill then |
313 | return nil, err | 317 | return nil, errfullfill |
314 | end | 318 | end |
315 | end | 319 | end |
316 | util.printout() | 320 | util.printout() |
@@ -324,28 +328,28 @@ function deps.fulfill_dependencies(rockspec, depskey, deps_mode, verify, deplock | |||
324 | return nil, err | 328 | return nil, err |
325 | end | 329 | end |
326 | 330 | ||
327 | deps.report_missing_dependencies(name, version, rockspec[depskey], deps_mode, rocks_provided) | 331 | deps.report_missing_dependencies(name, version, (rockspec)[depskey], deps_mode, rocks_provided) |
328 | 332 | ||
329 | util.printout() | 333 | util.printout() |
330 | 334 | ||
331 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, depskey) | 335 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, depskey) |
332 | for _, dep in ipairs(rockspec[depskey]) do | 336 | for _, dep in ipairs((rockspec)[depskey]) do |
333 | 337 | ||
334 | util.printout(("%s %s depends on %s (%s)"):format( | 338 | util.printout(("%s %s depends on %s (%s)"):format( |
335 | name, version, tostring(dep), rock_status(dep, get_versions))) | 339 | name, version, tostring(dep), rock_status(dep, get_versions))) |
336 | 340 | ||
337 | local ok, found_or_err, _, no_upgrade = deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey) | 341 | local okfulfill, found_or_err, _ = deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey) |
338 | if ok then | 342 | if okfulfill then |
339 | deplocks.add(depskey, dep.name, found_or_err) | 343 | deplocks.add(depskey, dep.name, found_or_err) |
340 | else | 344 | else |
341 | if no_upgrade then | 345 | |
342 | util.printerr("This version of "..name.." is designed for use with") | 346 | |
343 | util.printerr(tostring(dep)..", but is configured to avoid upgrading it") | 347 | |
344 | util.printerr("automatically. Please upgrade "..dep.name.." with") | 348 | |
345 | util.printerr(" luarocks install "..dep.name) | 349 | |
346 | util.printerr("or look for a suitable version of "..name.." with") | 350 | |
347 | util.printerr(" luarocks search "..name) | 351 | |
348 | end | 352 | |
349 | return nil, found_or_err | 353 | return nil, found_or_err |
350 | end | 354 | end |
351 | end | 355 | end |
@@ -353,28 +357,28 @@ function deps.fulfill_dependencies(rockspec, depskey, deps_mode, verify, deplock | |||
353 | return true | 357 | return true |
354 | end | 358 | end |
355 | 359 | ||
356 | --- If filename matches a pattern, return the capture. | 360 | |
357 | -- For example, given "libfoo.so" and "lib?.so" is a pattern, | 361 | |
358 | -- returns "foo" (which can then be used to build names | 362 | |
359 | -- based on other patterns. | 363 | |
360 | -- @param file string: a filename | 364 | |
361 | -- @param pattern string: a pattern, where ? is to be matched by the filename. | 365 | |
362 | -- @return string The pattern, if found, or nil. | 366 | |
363 | local function deconstruct_pattern(file, pattern) | 367 | local function deconstruct_pattern(file, pattern) |
364 | local depattern = "^"..(pattern:gsub("%.", "%%."):gsub("%*", ".*"):gsub("?", "(.*)")).."$" | 368 | local depattern = "^" .. (pattern:gsub("%.", "%%."):gsub("%*", ".*"):gsub("?", "(.*)")) .. "$" |
365 | return (file:match(depattern)) | 369 | return (file:match(depattern)) |
366 | end | 370 | end |
367 | 371 | ||
368 | --- Construct all possible patterns for a name and add to the files array. | 372 | |
369 | -- Run through the patterns array replacing all occurrences of "?" | 373 | |
370 | -- with the given file name and store them in the files array. | 374 | |
371 | -- @param file string A raw name (e.g. "foo") | 375 | |
372 | -- @param array of string An array of patterns with "?" as the wildcard | 376 | |
373 | -- (e.g. {"?.so", "lib?.so"}) | 377 | |
374 | -- @param files The array of constructed names | 378 | |
375 | local function add_all_patterns(file, patterns, files) | 379 | local function add_all_patterns(file, patterns, files) |
376 | for _, pattern in ipairs(patterns) do | 380 | for _, pattern in ipairs(patterns) do |
377 | table.insert(files, {#files + 1, (pattern:gsub("?", file))}) | 381 | table.insert(files, { #files + 1, (pattern:gsub("?", file)) }) |
378 | end | 382 | end |
379 | end | 383 | end |
380 | 384 | ||
@@ -388,7 +392,7 @@ local function get_external_deps_dirs(mode) | |||
388 | local dirs = { | 392 | local dirs = { |
389 | BINDIR = { subdir = subdirs.bin, testfile = "program", pattern = patterns.bin }, | 393 | BINDIR = { subdir = subdirs.bin, testfile = "program", pattern = patterns.bin }, |
390 | INCDIR = { subdir = subdirs.include, testfile = "header", pattern = patterns.include }, | 394 | INCDIR = { subdir = subdirs.include, testfile = "header", pattern = patterns.include }, |
391 | LIBDIR = { subdir = subdirs.lib, testfile = "library", pattern = patterns.lib } | 395 | LIBDIR = { subdir = subdirs.lib, testfile = "library", pattern = patterns.lib }, |
392 | } | 396 | } |
393 | if mode == "install" then | 397 | if mode == "install" then |
394 | dirs.INCDIR = nil | 398 | dirs.INCDIR = nil |
@@ -416,7 +420,7 @@ local function resolve_prefix(prefix, dirs) | |||
416 | end | 420 | end |
417 | 421 | ||
418 | local function add_patterns_for_file(files, file, patterns) | 422 | local function add_patterns_for_file(files, file, patterns) |
419 | -- If it doesn't look like it contains a filename extension | 423 | |
420 | if not (file:match("%.[a-z]+$") or file:match("%.[a-z]+%.")) then | 424 | if not (file:match("%.[a-z]+$") or file:match("%.[a-z]+%.")) then |
421 | add_all_patterns(file, patterns, files) | 425 | add_all_patterns(file, patterns, files) |
422 | else | 426 | else |
@@ -426,26 +430,35 @@ local function add_patterns_for_file(files, file, patterns) | |||
426 | add_all_patterns(matched, patterns, files) | 430 | add_all_patterns(matched, patterns, files) |
427 | end | 431 | end |
428 | end | 432 | end |
429 | table.insert(files, {#files + 1, file}) | 433 | table.insert(files, { #files + 1, file }) |
430 | end | 434 | end |
431 | end | 435 | end |
432 | 436 | ||
433 | local function check_external_dependency_at(prefix, name, ext_files, vars, dirs, err_files, cache) | 437 | local function check_external_dependency_at( |
438 | prefix, | ||
439 | name, | ||
440 | ext_files, | ||
441 | vars, | ||
442 | dirs, | ||
443 | err_files, | ||
444 | cache) | ||
445 | |||
434 | local fs = require("luarocks.fs") | 446 | local fs = require("luarocks.fs") |
435 | cache = cache or {} | 447 | cache = cache or {} |
436 | 448 | ||
437 | for dirname, dirdata in util.sortedpairs(dirs) do | 449 | for dirname, dirdata in util.sortedpairs(dirs) do |
438 | local paths | 450 | local paths |
439 | local path_var_value = vars[name.."_"..dirname] | 451 | local path_var_value = vars[name .. "_" .. dirname] |
452 | local dirdatastr = dirdata.subdir | ||
440 | if path_var_value then | 453 | if path_var_value then |
441 | paths = { path_var_value } | 454 | paths = { path_var_value } |
442 | elseif type(dirdata.subdir) == "table" then | 455 | elseif type(dirdatastr) == "table" then |
443 | paths = {} | 456 | paths = {} |
444 | for i,v in ipairs(dirdata.subdir) do | 457 | for i, v in ipairs(dirdatastr) do |
445 | paths[i] = dir.path(prefix, v) | 458 | paths[i] = dir.path(prefix, v) |
446 | end | 459 | end |
447 | else | 460 | else |
448 | paths = { dir.path(prefix, dirdata.subdir) } | 461 | paths = { dir.path(prefix, dirdatastr) } |
449 | end | 462 | end |
450 | local file_or_files = ext_files[dirdata.testfile] | 463 | local file_or_files = ext_files[dirdata.testfile] |
451 | if file_or_files then | 464 | if file_or_files then |
@@ -471,15 +484,15 @@ local function check_external_dependency_at(prefix, name, ext_files, vars, dirs, | |||
471 | for _, fa in ipairs(files) do | 484 | for _, fa in ipairs(files) do |
472 | 485 | ||
473 | local f = fa[2] | 486 | local f = fa[2] |
474 | -- small convenience hack | 487 | |
475 | if f:match("%.so$") or f:match("%.dylib$") or f:match("%.dll$") then | 488 | if f:match("%.so$") or f:match("%.dylib$") or f:match("%.dll$") then |
476 | f = f:gsub("%.[^.]+$", "."..cfg.external_lib_extension) | 489 | f = f:gsub("%.[^.]+$", "." .. cfg.external_lib_extension) |
477 | end | 490 | end |
478 | 491 | ||
479 | local pattern | 492 | local pattern |
480 | if f:match("%*") then | 493 | if f:match("%*") then |
481 | pattern = "^" .. f:gsub("([-.+])", "%%%1"):gsub("%*", ".*") .. "$" | 494 | pattern = "^" .. f:gsub("([-.+])", "%%%1"):gsub("%*", ".*") .. "$" |
482 | f = "matching "..f | 495 | f = "matching " .. f |
483 | end | 496 | end |
484 | 497 | ||
485 | for _, d in ipairs(paths) do | 498 | for _, d in ipairs(paths) do |
@@ -502,7 +515,7 @@ local function check_external_dependency_at(prefix, name, ext_files, vars, dirs, | |||
502 | dirdata.file = f | 515 | dirdata.file = f |
503 | break | 516 | break |
504 | else | 517 | else |
505 | table.insert(err_files[dirdata.testfile], f.." in "..d) | 518 | table.insert(err_files[dirdata.testfile], f .. " in " .. d) |
506 | end | 519 | end |
507 | end | 520 | end |
508 | if found then | 521 | if found then |
@@ -513,9 +526,9 @@ local function check_external_dependency_at(prefix, name, ext_files, vars, dirs, | |||
513 | return nil, dirname, dirdata.testfile | 526 | return nil, dirname, dirdata.testfile |
514 | end | 527 | end |
515 | else | 528 | else |
516 | -- When we have a set of subdir suffixes, look for one that exists. | 529 | |
517 | -- For these reason, we now put "lib" ahead of "" on Windows in our | 530 | |
518 | -- default set. | 531 | |
519 | dirdata.dir = paths[1] | 532 | dirdata.dir = paths[1] |
520 | for _, p in ipairs(paths) do | 533 | for _, p in ipairs(paths) do |
521 | if fs.exists(p) then | 534 | if fs.exists(p) then |
@@ -527,18 +540,23 @@ local function check_external_dependency_at(prefix, name, ext_files, vars, dirs, | |||
527 | end | 540 | end |
528 | 541 | ||
529 | for dirname, dirdata in pairs(dirs) do | 542 | for dirname, dirdata in pairs(dirs) do |
530 | vars[name.."_"..dirname] = dirdata.dir | 543 | vars[name .. "_" .. dirname] = dirdata.dir |
531 | vars[name.."_"..dirname.."_FILE"] = dirdata.file | 544 | vars[name .. "_" .. dirname .. "_FILE"] = dirdata.file |
532 | end | 545 | end |
533 | vars[name.."_DIR"] = prefix | 546 | vars[name .. "_DIR"] = prefix |
534 | return true | 547 | return true |
535 | end | 548 | end |
536 | 549 | ||
537 | local function check_external_dependency(name, ext_files, vars, mode, cache) | 550 | local function check_external_dependency( |
551 | name, | ||
552 | ext_files, | ||
553 | vars, | ||
554 | mode, | ||
555 | cache) | ||
538 | local ok | 556 | local ok |
539 | local err_dirname | 557 | local err_dirname |
540 | local err_testfile | 558 | local err_testfile |
541 | local err_files = {program = {}, header = {}, library = {}} | 559 | local err_files = { program = {}, header = {}, library = {} } |
542 | 560 | ||
543 | local dirs = get_external_deps_dirs(mode) | 561 | local dirs = get_external_deps_dirs(mode) |
544 | 562 | ||
@@ -572,7 +590,7 @@ local function check_external_dependency(name, ext_files, vars, mode, cache) | |||
572 | end | 590 | end |
573 | 591 | ||
574 | function deps.autodetect_external_dependencies(build) | 592 | function deps.autodetect_external_dependencies(build) |
575 | -- only applies to the 'builtin' build type | 593 | |
576 | if not build or not build.modules then | 594 | if not build or not build.modules then |
577 | return nil | 595 | return nil |
578 | end | 596 | end |
@@ -581,9 +599,12 @@ function deps.autodetect_external_dependencies(build) | |||
581 | local any = false | 599 | local any = false |
582 | for _, data in pairs(build.modules) do | 600 | for _, data in pairs(build.modules) do |
583 | if type(data) == "table" and data.libraries then | 601 | if type(data) == "table" and data.libraries then |
584 | local libraries = data.libraries | 602 | local libraries |
585 | if type(libraries) == "string" then | 603 | local librariesstr = data.libraries |
586 | libraries = { libraries } | 604 | if type(librariesstr) == "string" then |
605 | libraries = { librariesstr } | ||
606 | else | ||
607 | libraries = librariesstr | ||
587 | end | 608 | end |
588 | local incdirs = {} | 609 | local incdirs = {} |
589 | local libdirs = {} | 610 | local libdirs = {} |
@@ -605,21 +626,20 @@ function deps.autodetect_external_dependencies(build) | |||
605 | return any and extdeps or nil | 626 | return any and extdeps or nil |
606 | end | 627 | end |
607 | 628 | ||
608 | --- Set up path-related variables for external dependencies. | 629 | |
609 | -- For each key in the external_dependencies table in the | 630 | |
610 | -- rockspec file, four variables are created: <key>_DIR, <key>_BINDIR, | 631 | |
611 | -- <key>_INCDIR and <key>_LIBDIR. These are not overwritten | 632 | |
612 | -- if already set (e.g. by the LuaRocks config file or through the | 633 | |
613 | -- command-line). Values in the external_dependencies table | 634 | |
614 | -- are tables that may contain a "header" or a "library" field, | 635 | |
615 | -- with filenames to be tested for existence. | 636 | |
616 | -- @param rockspec table: The rockspec table. | 637 | |
617 | -- @param mode string: if "build" is given, checks all files; | 638 | |
618 | -- if "install" is given, do not scan for headers. | 639 | |
619 | -- @return boolean or (nil, string): True if no errors occurred, or | 640 | |
620 | -- nil and an error message if any test failed. | 641 | |
621 | function deps.check_external_deps(rockspec, mode) | 642 | function deps.check_external_deps(rockspec, mode) |
622 | assert(rockspec:type() == "rockspec") | ||
623 | 643 | ||
624 | if not rockspec.external_dependencies then | 644 | if not rockspec.external_dependencies then |
625 | rockspec.external_dependencies = deps.autodetect_external_dependencies(rockspec.build) | 645 | rockspec.external_dependencies = deps.autodetect_external_dependencies(rockspec.build) |
@@ -628,21 +648,21 @@ function deps.check_external_deps(rockspec, mode) | |||
628 | return true | 648 | return true |
629 | end | 649 | end |
630 | 650 | ||
631 | for name, ext_files in util.sortedpairs(rockspec.external_dependencies) do | 651 | for name, ext_files in util.sortedpairs(rockspec.external_dependencies.queries) do |
632 | local ok, err_dirname, err_testfile, err_files = check_external_dependency(name, ext_files, rockspec.variables, mode) | 652 | local ok, err_dirname, err_testfile, err_files = check_external_dependency(name, ext_files, rockspec.variables, mode) |
633 | if not ok then | 653 | if not ok then |
634 | local lines = {"Could not find "..err_testfile.." file for "..name} | 654 | local lines = { "Could not find " .. err_testfile .. " file for " .. name } |
635 | 655 | ||
636 | local err_paths = {} | 656 | local err_paths = {} |
637 | for _, err_file in ipairs(err_files[err_testfile]) do | 657 | for _, err_file in ipairs(err_files[err_testfile]) do |
638 | if not err_paths[err_file] then | 658 | if not err_paths[err_file] then |
639 | err_paths[err_file] = true | 659 | err_paths[err_file] = true |
640 | table.insert(lines, " No file "..err_file) | 660 | table.insert(lines, " No file " .. err_file) |
641 | end | 661 | end |
642 | end | 662 | end |
643 | 663 | ||
644 | table.insert(lines, "You may have to install "..name.." in your system and/or pass "..name.."_DIR or "..name.."_"..err_dirname.." to the luarocks command.") | 664 | table.insert(lines, "You may have to install " .. name .. " in your system and/or pass " .. name .. "_DIR or " .. name .. "_" .. err_dirname .. " to the luarocks command.") |
645 | table.insert(lines, "Example: luarocks install "..rockspec.name.." "..name.."_DIR=/usr/local") | 665 | table.insert(lines, "Example: luarocks install " .. rockspec.name .. " " .. name .. "_DIR=/usr/local") |
646 | 666 | ||
647 | return nil, table.concat(lines, "\n"), "dependency" | 667 | return nil, table.concat(lines, "\n"), "dependency" |
648 | end | 668 | end |
@@ -650,18 +670,17 @@ function deps.check_external_deps(rockspec, mode) | |||
650 | return true | 670 | return true |
651 | end | 671 | end |
652 | 672 | ||
653 | --- Recursively add satisfied dependencies of a package to a table, | 673 | |
654 | -- to build a transitive closure of all dependent packages. | 674 | |
655 | -- Additionally ensures that `dependencies` table of the manifest is up-to-date. | 675 | |
656 | -- @param results table: The results table being built, maps package names to versions. | 676 | |
657 | -- @param mdeps table: The manifest dependencies table. | 677 | |
658 | -- @param name string: Package name. | 678 | |
659 | -- @param version string: Package version. | 679 | |
660 | function deps.scan_deps(results, mdeps, name, version, deps_mode) | 680 | function deps.scan_deps(results, mdeps, name, version, deps_mode) |
661 | assert(type(results) == "table") | 681 | assert(type(results) == "table") |
662 | assert(type(mdeps) == "table") | 682 | assert(type(mdeps) == "table") |
663 | assert(type(name) == "string" and not name:match("/")) | 683 | assert(not name:match("/")) |
664 | assert(type(version) == "string") | ||
665 | 684 | ||
666 | local fetch = require("luarocks.fetch") | 685 | local fetch = require("luarocks.fetch") |
667 | 686 | ||
@@ -673,11 +692,11 @@ function deps.scan_deps(results, mdeps, name, version, deps_mode) | |||
673 | local dependencies = mdn[version] | 692 | local dependencies = mdn[version] |
674 | local rocks_provided | 693 | local rocks_provided |
675 | if not dependencies then | 694 | if not dependencies then |
676 | local rockspec, err = fetch.load_local_rockspec(path.rockspec_file(name, version), false) | 695 | local rockspec = fetch.load_local_rockspec(path.rockspec_file(name, version), false) |
677 | if not rockspec then | 696 | if not rockspec then |
678 | return | 697 | return |
679 | end | 698 | end |
680 | dependencies = rockspec.dependencies | 699 | dependencies = rockspec.dependencies.queries |
681 | rocks_provided = rockspec.rocks_provided | 700 | rocks_provided = rockspec.rocks_provided |
682 | mdn[version] = dependencies | 701 | mdn[version] = dependencies |
683 | else | 702 | else |
@@ -736,13 +755,13 @@ local function find_lua_incdir(prefix, luaver, luajitver) | |||
736 | end | 755 | end |
737 | end | 756 | end |
738 | 757 | ||
739 | -- not found, will fallback to a default | 758 | |
740 | return nil, mainerr | 759 | return nil, mainerr |
741 | end | 760 | end |
742 | 761 | ||
743 | function deps.check_lua_incdir(vars) | 762 | function deps.check_lua_incdir(vars) |
744 | if vars.LUA_INCDIR_OK == true | 763 | if vars.LUA_INCDIR_OK == true then |
745 | then return true | 764 | return true |
746 | end | 765 | end |
747 | 766 | ||
748 | local ljv = util.get_luajit_version() | 767 | local ljv = util.get_luajit_version() |
@@ -769,8 +788,8 @@ function deps.check_lua_incdir(vars) | |||
769 | end | 788 | end |
770 | 789 | ||
771 | function deps.check_lua_libdir(vars) | 790 | function deps.check_lua_libdir(vars) |
772 | if vars.LUA_LIBDIR_OK == true | 791 | if vars.LUA_LIBDIR_OK == true then |
773 | then return true | 792 | return true |
774 | end | 793 | end |
775 | 794 | ||
776 | local fs = require("luarocks.fs") | 795 | local fs = require("luarocks.fs") |
@@ -803,10 +822,10 @@ function deps.check_lua_libdir(vars) | |||
803 | local fd = io.open(filename, "r") | 822 | local fd = io.open(filename, "r") |
804 | if fd then | 823 | if fd then |
805 | if not vars.LUA_LIBDIR_FILE:match((cfg.lua_version:gsub("%.", "%%.?"))) then | 824 | if not vars.LUA_LIBDIR_FILE:match((cfg.lua_version:gsub("%.", "%%.?"))) then |
806 | -- if filename isn't versioned, check file contents | 825 | |
807 | local txt = fd:read("*a") | 826 | local txt = fd:read("*a") |
808 | ok = txt:match("Lua " .. cfg.lua_version, 1, true) | 827 | ok = txt:find("Lua " .. cfg.lua_version, 1, true) or |
809 | or txt:match("lua" .. (cfg.lua_version:gsub("%.", "")), 1, true) | 828 | txt:find("lua" .. (cfg.lua_version:gsub("%.", "")), 1, true) |
810 | if not ok then | 829 | if not ok then |
811 | err = "Lua library at " .. filename .. " does not match Lua version " .. cfg.lua_version .. ". You can use `luarocks config variables.LUA_LIBDIR <path>` to set the correct location." | 830 | err = "Lua library at " .. filename .. " does not match Lua version " .. cfg.lua_version .. ". You can use `luarocks config variables.LUA_LIBDIR <path>` to set the correct location." |
812 | end | 831 | end |
diff --git a/src/luarocks/deps.lua b/src/luarocks/deps.lua index df2fbbd5..1a9eefde 100644 --- a/src/luarocks/deps.lua +++ b/src/luarocks/deps.lua | |||
@@ -1,8 +1,7 @@ | |||
1 | local _tl_compat; if (tonumber((_VERSION or ''):match('[%d.]*$')) or 0) < 5.3 then local p, m = pcall(require, 'compat53.module'); if p then _tl_compat = m end end; local assert = _tl_compat and _tl_compat.assert or assert; local io = _tl_compat and _tl_compat.io or io; local ipairs = _tl_compat and _tl_compat.ipairs or ipairs; local pairs = _tl_compat and _tl_compat.pairs or pairs; local string = _tl_compat and _tl_compat.string or string; local table = _tl_compat and _tl_compat.table or table | ||
2 | 1 | ||
2 | --- High-level dependency related functions. | ||
3 | local deps = {} | 3 | local deps = {} |
4 | 4 | ||
5 | |||
6 | local cfg = require("luarocks.core.cfg") | 5 | local cfg = require("luarocks.core.cfg") |
7 | local manif = require("luarocks.manif") | 6 | local manif = require("luarocks.manif") |
8 | local path = require("luarocks.path") | 7 | local path = require("luarocks.path") |
@@ -13,55 +12,34 @@ local vers = require("luarocks.core.vers") | |||
13 | local queries = require("luarocks.queries") | 12 | local queries = require("luarocks.queries") |
14 | local deplocks = require("luarocks.deplocks") | 13 | local deplocks = require("luarocks.deplocks") |
15 | 14 | ||
16 | 15 | --- Generate a function that matches dep queries against the manifest, | |
17 | 16 | -- taking into account rocks_provided, the list of versions to skip, | |
18 | 17 | -- and the lockfile. | |
19 | 18 | -- @param deps_mode "one", "none", "all" or "order" | |
20 | 19 | -- @param rocks_provided a one-level table mapping names to versions, | |
21 | 20 | -- listing rocks to consider provided by the VM | |
22 | 21 | -- @param rocks_provided table: A table of auto-provided dependencies. | |
23 | 22 | -- by this Lua implementation for the given dependency. | |
24 | 23 | -- @param depskey key to use when matching the lockfile ("dependencies", | |
25 | 24 | -- "build_dependencies", etc.) | |
26 | 25 | -- @param skip_set a two-level table mapping names to versions to | |
27 | 26 | -- boolean, listing rocks that should not be matched | |
28 | 27 | -- @return function(dep): {string}, {string:string}, string, boolean | |
29 | 28 | -- * array of matching versions | |
30 | 29 | -- * map of versions to locations | |
31 | 30 | -- * version matched via lockfile if any | |
32 | 31 | -- * true if rock matched via rocks_provided | |
33 | |||
34 | |||
35 | |||
36 | |||
37 | |||
38 | |||
39 | |||
40 | |||
41 | |||
42 | |||
43 | |||
44 | |||
45 | |||
46 | |||
47 | |||
48 | |||
49 | |||
50 | |||
51 | |||
52 | |||
53 | |||
54 | |||
55 | |||
56 | |||
57 | |||
58 | local function prepare_get_versions(deps_mode, rocks_provided, depskey, skip_set) | 32 | local function prepare_get_versions(deps_mode, rocks_provided, depskey, skip_set) |
33 | assert(type(deps_mode) == "string") | ||
34 | assert(type(rocks_provided) == "table") | ||
35 | assert(type(depskey) == "string") | ||
36 | assert(type(skip_set) == "table" or skip_set == nil) | ||
59 | 37 | ||
60 | return function(dep) | 38 | return function(dep) |
61 | local versions, locations | 39 | local versions, locations |
62 | local provided = rocks_provided[dep.name] | 40 | local provided = rocks_provided[dep.name] |
63 | if provided then | 41 | if provided then |
64 | 42 | -- Provided rocks have higher priority than manifest's rocks. | |
65 | versions, locations = { provided }, {} | 43 | versions, locations = { provided }, {} |
66 | else | 44 | else |
67 | if deps_mode == "none" then | 45 | if deps_mode == "none" then |
@@ -85,20 +63,21 @@ local function prepare_get_versions(deps_mode, rocks_provided, depskey, skip_set | |||
85 | end | 63 | end |
86 | end | 64 | end |
87 | 65 | ||
88 | 66 | --- Attempt to match a dependency to an installed rock. | |
89 | 67 | -- @param get_versions a getter function obtained via prepare_get_versions | |
90 | 68 | -- @return (string, string, table) or (nil, nil, table): | |
91 | 69 | -- 1. latest installed version of the rock matching the dependency | |
92 | 70 | -- 2. location where the installed version is installed | |
93 | 71 | -- 3. the 'dep' query table | |
94 | 72 | -- 4. true if provided via VM | |
95 | 73 | -- or | |
96 | 74 | -- 1. nil | |
97 | 75 | -- 2. nil | |
98 | 76 | -- 3. either 'dep' or an alternative query to be used | |
99 | 77 | -- 4. false | |
100 | local function match_dep(dep, | 78 | local function match_dep(dep, get_versions) |
101 | get_versions) | 79 | assert(type(dep) == "table") |
80 | assert(type(get_versions) == "function") | ||
102 | 81 | ||
103 | local versions, locations, lockversion, provided = get_versions(dep) | 82 | local versions, locations, lockversion, provided = get_versions(dep) |
104 | 83 | ||
@@ -126,8 +105,9 @@ local function match_dep(dep, | |||
126 | return latest_vstring, locations[latest_vstring], dep, provided | 105 | return latest_vstring, locations[latest_vstring], dep, provided |
127 | end | 106 | end |
128 | 107 | ||
129 | local function match_all_deps(dependencies, | 108 | local function match_all_deps(dependencies, get_versions) |
130 | get_versions) | 109 | assert(type(dependencies) == "table") |
110 | assert(type(get_versions) == "function") | ||
131 | 111 | ||
132 | local matched, missing, no_upgrade = {}, {}, {} | 112 | local matched, missing, no_upgrade = {}, {}, {} |
133 | 113 | ||
@@ -136,7 +116,7 @@ local function match_all_deps(dependencies, | |||
136 | found, _, dep, provided = match_dep(dep, get_versions) | 116 | found, _, dep, provided = match_dep(dep, get_versions) |
137 | if found then | 117 | if found then |
138 | if not provided then | 118 | if not provided then |
139 | matched[dep] = { name = dep.name, version = found } | 119 | matched[dep] = {name = dep.name, version = found} |
140 | end | 120 | end |
141 | else | 121 | else |
142 | if dep.constraints[1] and dep.constraints[1].no_upgrade then | 122 | if dep.constraints[1] and dep.constraints[1].no_upgrade then |
@@ -149,41 +129,53 @@ local function match_all_deps(dependencies, | |||
149 | return matched, missing, no_upgrade | 129 | return matched, missing, no_upgrade |
150 | end | 130 | end |
151 | 131 | ||
152 | 132 | --- Attempt to match dependencies of a rockspec to installed rocks. | |
153 | 133 | -- @param dependencies table: The table of dependencies. | |
154 | 134 | -- @param rocks_provided table: The table of auto-provided dependencies. | |
155 | 135 | -- @param skip_set table or nil: Program versions to not use as valid matches. | |
156 | 136 | -- Table where keys are program names and values are tables where keys | |
157 | 137 | -- are program versions and values are 'true'. | |
158 | 138 | -- @param deps_mode string: Which trees to check dependencies for | |
159 | 139 | -- @return table, table, table: A table where keys are dependencies parsed | |
160 | 140 | -- in table format and values are tables containing fields 'name' and | |
161 | 141 | -- version' representing matches; a table of missing dependencies | |
162 | 142 | -- parsed as tables; and a table of "no-upgrade" missing dependencies | |
163 | 143 | -- (to be used in plugin modules so that a plugin does not force upgrade of | |
164 | 144 | -- its parent application). | |
165 | function deps.match_deps(dependencies, rocks_provided, deps_mode, skip_set) | 145 | function deps.match_deps(dependencies, rocks_provided, deps_mode, skip_set) |
146 | assert(type(dependencies) == "table") | ||
147 | assert(type(rocks_provided) == "table") | ||
148 | assert(type(skip_set) == "table" or skip_set == nil) | ||
149 | assert(type(deps_mode) == "string") | ||
166 | 150 | ||
167 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, "dependencies", skip_set) | 151 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, "dependencies", skip_set) |
168 | return match_all_deps(dependencies, get_versions) | 152 | return match_all_deps(dependencies, get_versions) |
169 | end | 153 | end |
170 | 154 | ||
171 | local function rock_status(dep, get_versions) | 155 | local function rock_status(dep, get_versions) |
156 | assert(dep:type() == "query") | ||
157 | assert(type(get_versions) == "function") | ||
158 | |||
172 | local installed, _, _, provided = match_dep(dep, get_versions) | 159 | local installed, _, _, provided = match_dep(dep, get_versions) |
173 | local installation_type = provided and "provided by VM" or "installed" | 160 | local installation_type = provided and "provided by VM" or "installed" |
174 | return installed and installed .. " " .. installation_type .. ": success" or "not installed" | 161 | return installed and installed.." "..installation_type..": success" or "not installed" |
175 | end | 162 | end |
176 | 163 | ||
177 | 164 | --- Check depenendencies of a package and report any missing ones. | |
178 | 165 | -- @param name string: package name. | |
179 | 166 | -- @param version string: package version. | |
180 | 167 | -- @param dependencies table: array of dependencies. | |
181 | 168 | -- @param deps_mode string: Which trees to check dependencies for | |
182 | 169 | -- @param rocks_provided table: A table of auto-dependencies provided | |
183 | 170 | -- by this Lua implementation for the given dependency. | |
184 | 171 | -- "one" for the current default tree, "all" for all trees, | |
185 | 172 | -- "order" for all trees with priority >= the current default, "none" for no trees. | |
186 | function deps.report_missing_dependencies(name, version, dependencies, deps_mode, rocks_provided) | 173 | function deps.report_missing_dependencies(name, version, dependencies, deps_mode, rocks_provided) |
174 | assert(type(name) == "string") | ||
175 | assert(type(version) == "string") | ||
176 | assert(type(dependencies) == "table") | ||
177 | assert(type(deps_mode) == "string") | ||
178 | assert(type(rocks_provided) == "table") | ||
187 | 179 | ||
188 | if deps_mode == "none" then | 180 | if deps_mode == "none" then |
189 | return | 181 | return |
@@ -208,6 +200,11 @@ function deps.report_missing_dependencies(name, version, dependencies, deps_mode | |||
208 | end | 200 | end |
209 | 201 | ||
210 | function deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey) | 202 | function deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey) |
203 | assert(dep:type() == "query") | ||
204 | assert(type(deps_mode) == "string" or deps_mode == nil) | ||
205 | assert(type(rocks_provided) == "table" or rocks_provided == nil) | ||
206 | assert(type(verify) == "boolean" or verify == nil) | ||
207 | assert(type(depskey) == "string") | ||
211 | 208 | ||
212 | deps_mode = deps_mode or "all" | 209 | deps_mode = deps_mode or "all" |
213 | rocks_provided = rocks_provided or {} | 210 | rocks_provided = rocks_provided or {} |
@@ -227,9 +224,9 @@ function deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey | |||
227 | 224 | ||
228 | local url, search_err = search.find_suitable_rock(dep) | 225 | local url, search_err = search.find_suitable_rock(dep) |
229 | if not url then | 226 | if not url then |
230 | return nil, "Could not satisfy dependency " .. tostring(dep) .. ": " .. search_err | 227 | return nil, "Could not satisfy dependency "..tostring(dep)..": "..search_err |
231 | end | 228 | end |
232 | util.printout("Installing " .. url) | 229 | util.printout("Installing "..url) |
233 | local install_args = { | 230 | local install_args = { |
234 | rock = url, | 231 | rock = url, |
235 | deps_mode = deps_mode, | 232 | deps_mode = deps_mode, |
@@ -238,7 +235,7 @@ function deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey | |||
238 | } | 235 | } |
239 | local ok, install_err, errcode = install.command(install_args) | 236 | local ok, install_err, errcode = install.command(install_args) |
240 | if not ok then | 237 | if not ok then |
241 | return nil, "Failed installing dependency: " .. url .. " - " .. install_err, errcode | 238 | return nil, "Failed installing dependency: "..url.." - "..install_err, errcode |
242 | end | 239 | end |
243 | 240 | ||
244 | found, where = match_dep(dep, get_versions) | 241 | found, where = match_dep(dep, get_versions) |
@@ -249,15 +246,15 @@ function deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey | |||
249 | end | 246 | end |
250 | 247 | ||
251 | local function check_supported_platforms(rockspec) | 248 | local function check_supported_platforms(rockspec) |
252 | if rockspec.supported_platforms and next(rockspec.supported_platforms) ~= nil then | 249 | if rockspec.supported_platforms and next(rockspec.supported_platforms) then |
253 | local all_negative = true | 250 | local all_negative = true |
254 | local supported = false | 251 | local supported = false |
255 | for _, plat in ipairs(rockspec.supported_platforms) do | 252 | for _, plat in pairs(rockspec.supported_platforms) do |
256 | local neg | 253 | local neg |
257 | neg, plat = plat:match("^(!?)(.*)") | 254 | neg, plat = plat:match("^(!?)(.*)") |
258 | if neg == "!" then | 255 | if neg == "!" then |
259 | if cfg.is_platform(plat) then | 256 | if cfg.is_platform(plat) then |
260 | return nil, "This rockspec for " .. rockspec.package .. " does not support " .. plat .. " platforms." | 257 | return nil, "This rockspec for "..rockspec.package.." does not support "..plat.." platforms." |
261 | end | 258 | end |
262 | else | 259 | else |
263 | all_negative = false | 260 | all_negative = false |
@@ -269,26 +266,32 @@ local function check_supported_platforms(rockspec) | |||
269 | end | 266 | end |
270 | if supported == false and not all_negative then | 267 | if supported == false and not all_negative then |
271 | local plats = cfg.print_platforms() | 268 | local plats = cfg.print_platforms() |
272 | return nil, "This rockspec for " .. rockspec.package .. " does not support " .. plats .. " platforms." | 269 | return nil, "This rockspec for "..rockspec.package.." does not support "..plats.." platforms." |
273 | end | 270 | end |
274 | end | 271 | end |
275 | 272 | ||
276 | return true | 273 | return true |
277 | end | 274 | end |
278 | 275 | ||
279 | 276 | --- Check dependencies of a rock and attempt to install any missing ones. | |
280 | 277 | -- Packages are installed using the LuaRocks "install" command. | |
281 | 278 | -- Aborts the program if a dependency could not be fulfilled. | |
282 | 279 | -- @param rockspec table: A rockspec in table format. | |
283 | 280 | -- @param depskey string: Rockspec key to fetch to get dependency table | |
284 | 281 | -- ("dependencies", "build_dependencies", etc.). | |
285 | 282 | -- @param deps_mode string | |
286 | 283 | -- @param verify boolean | |
287 | 284 | -- @param deplock_dir string: dirname of the deplock file | |
288 | 285 | -- @return boolean or (nil, string, [string]): True if no errors occurred, or | |
289 | 286 | -- nil and an error message if any test failed, followed by an optional | |
290 | 287 | -- error code. | |
291 | function deps.fulfill_dependencies(rockspec, depskey, deps_mode, verify, deplock_dir) | 288 | function deps.fulfill_dependencies(rockspec, depskey, deps_mode, verify, deplock_dir) |
289 | assert(type(rockspec) == "table") | ||
290 | assert(type(depskey) == "string") | ||
291 | assert(type(deps_mode) == "string") | ||
292 | assert(type(verify) == "boolean" or verify == nil) | ||
293 | assert(type(deplock_dir) == "string" or deplock_dir == nil) | ||
294 | |||
292 | local name = rockspec.name | 295 | local name = rockspec.name |
293 | local version = rockspec.version | 296 | local version = rockspec.version |
294 | local rocks_provided = rockspec.rocks_provided | 297 | local rocks_provided = rockspec.rocks_provided |
@@ -298,23 +301,16 @@ function deps.fulfill_dependencies(rockspec, depskey, deps_mode, verify, deplock | |||
298 | util.printout("Using dependencies pinned in lockfile: " .. filename) | 301 | util.printout("Using dependencies pinned in lockfile: " .. filename) |
299 | 302 | ||
300 | local get_versions = prepare_get_versions("none", rocks_provided, depskey) | 303 | local get_versions = prepare_get_versions("none", rocks_provided, depskey) |
301 | local dnsnamestr, dversionstr | ||
302 | for dnsname, dversion in deplocks.each(depskey) do | 304 | for dnsname, dversion in deplocks.each(depskey) do |
303 | if type(dnsname) == "string" then | 305 | local dname, dnamespace = util.split_namespace(dnsname) |
304 | dnsnamestr = dnsname | 306 | local dep = queries.new(dname, dnamespace, dversion) |
305 | end | ||
306 | if type(dversion) == "string" then | ||
307 | dversionstr = dversion | ||
308 | end | ||
309 | local dname, dnamespace = util.split_namespace(dnsnamestr) | ||
310 | local dep = queries.new(dname, dnamespace, dversionstr) | ||
311 | 307 | ||
312 | util.printout(("%s %s is pinned to %s (%s)"):format( | 308 | util.printout(("%s %s is pinned to %s (%s)"):format( |
313 | name, version, tostring(dep), rock_status(dep, get_versions))) | 309 | name, version, tostring(dep), rock_status(dep, get_versions))) |
314 | 310 | ||
315 | local okfullfill, errfullfill = deps.fulfill_dependency(dep, "none", rocks_provided, verify, depskey) | 311 | local ok, err = deps.fulfill_dependency(dep, "none", rocks_provided, verify, depskey) |
316 | if not okfullfill then | 312 | if not ok then |
317 | return nil, errfullfill | 313 | return nil, err |
318 | end | 314 | end |
319 | end | 315 | end |
320 | util.printout() | 316 | util.printout() |
@@ -328,28 +324,28 @@ function deps.fulfill_dependencies(rockspec, depskey, deps_mode, verify, deplock | |||
328 | return nil, err | 324 | return nil, err |
329 | end | 325 | end |
330 | 326 | ||
331 | deps.report_missing_dependencies(name, version, (rockspec)[depskey], deps_mode, rocks_provided) | 327 | deps.report_missing_dependencies(name, version, rockspec[depskey], deps_mode, rocks_provided) |
332 | 328 | ||
333 | util.printout() | 329 | util.printout() |
334 | 330 | ||
335 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, depskey) | 331 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, depskey) |
336 | for _, dep in ipairs((rockspec)[depskey]) do | 332 | for _, dep in ipairs(rockspec[depskey]) do |
337 | 333 | ||
338 | util.printout(("%s %s depends on %s (%s)"):format( | 334 | util.printout(("%s %s depends on %s (%s)"):format( |
339 | name, version, tostring(dep), rock_status(dep, get_versions))) | 335 | name, version, tostring(dep), rock_status(dep, get_versions))) |
340 | 336 | ||
341 | local okfulfill, found_or_err, _ = deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey) | 337 | local ok, found_or_err, _, no_upgrade = deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey) |
342 | if okfulfill then | 338 | if ok then |
343 | deplocks.add(depskey, dep.name, found_or_err) | 339 | deplocks.add(depskey, dep.name, found_or_err) |
344 | else | 340 | else |
345 | 341 | if no_upgrade then | |
346 | 342 | util.printerr("This version of "..name.." is designed for use with") | |
347 | 343 | util.printerr(tostring(dep)..", but is configured to avoid upgrading it") | |
348 | 344 | util.printerr("automatically. Please upgrade "..dep.name.." with") | |
349 | 345 | util.printerr(" luarocks install "..dep.name) | |
350 | 346 | util.printerr("or look for a suitable version of "..name.." with") | |
351 | 347 | util.printerr(" luarocks search "..name) | |
352 | 348 | end | |
353 | return nil, found_or_err | 349 | return nil, found_or_err |
354 | end | 350 | end |
355 | end | 351 | end |
@@ -357,28 +353,28 @@ function deps.fulfill_dependencies(rockspec, depskey, deps_mode, verify, deplock | |||
357 | return true | 353 | return true |
358 | end | 354 | end |
359 | 355 | ||
360 | 356 | --- If filename matches a pattern, return the capture. | |
361 | 357 | -- For example, given "libfoo.so" and "lib?.so" is a pattern, | |
362 | 358 | -- returns "foo" (which can then be used to build names | |
363 | 359 | -- based on other patterns. | |
364 | 360 | -- @param file string: a filename | |
365 | 361 | -- @param pattern string: a pattern, where ? is to be matched by the filename. | |
366 | 362 | -- @return string The pattern, if found, or nil. | |
367 | local function deconstruct_pattern(file, pattern) | 363 | local function deconstruct_pattern(file, pattern) |
368 | local depattern = "^" .. (pattern:gsub("%.", "%%."):gsub("%*", ".*"):gsub("?", "(.*)")) .. "$" | 364 | local depattern = "^"..(pattern:gsub("%.", "%%."):gsub("%*", ".*"):gsub("?", "(.*)")).."$" |
369 | return (file:match(depattern)) | 365 | return (file:match(depattern)) |
370 | end | 366 | end |
371 | 367 | ||
372 | 368 | --- Construct all possible patterns for a name and add to the files array. | |
373 | 369 | -- Run through the patterns array replacing all occurrences of "?" | |
374 | 370 | -- with the given file name and store them in the files array. | |
375 | 371 | -- @param file string A raw name (e.g. "foo") | |
376 | 372 | -- @param array of string An array of patterns with "?" as the wildcard | |
377 | 373 | -- (e.g. {"?.so", "lib?.so"}) | |
378 | 374 | -- @param files The array of constructed names | |
379 | local function add_all_patterns(file, patterns, files) | 375 | local function add_all_patterns(file, patterns, files) |
380 | for _, pattern in ipairs(patterns) do | 376 | for _, pattern in ipairs(patterns) do |
381 | table.insert(files, { #files + 1, (pattern:gsub("?", file)) }) | 377 | table.insert(files, {#files + 1, (pattern:gsub("?", file))}) |
382 | end | 378 | end |
383 | end | 379 | end |
384 | 380 | ||
@@ -392,7 +388,7 @@ local function get_external_deps_dirs(mode) | |||
392 | local dirs = { | 388 | local dirs = { |
393 | BINDIR = { subdir = subdirs.bin, testfile = "program", pattern = patterns.bin }, | 389 | BINDIR = { subdir = subdirs.bin, testfile = "program", pattern = patterns.bin }, |
394 | INCDIR = { subdir = subdirs.include, testfile = "header", pattern = patterns.include }, | 390 | INCDIR = { subdir = subdirs.include, testfile = "header", pattern = patterns.include }, |
395 | LIBDIR = { subdir = subdirs.lib, testfile = "library", pattern = patterns.lib }, | 391 | LIBDIR = { subdir = subdirs.lib, testfile = "library", pattern = patterns.lib } |
396 | } | 392 | } |
397 | if mode == "install" then | 393 | if mode == "install" then |
398 | dirs.INCDIR = nil | 394 | dirs.INCDIR = nil |
@@ -420,7 +416,7 @@ local function resolve_prefix(prefix, dirs) | |||
420 | end | 416 | end |
421 | 417 | ||
422 | local function add_patterns_for_file(files, file, patterns) | 418 | local function add_patterns_for_file(files, file, patterns) |
423 | 419 | -- If it doesn't look like it contains a filename extension | |
424 | if not (file:match("%.[a-z]+$") or file:match("%.[a-z]+%.")) then | 420 | if not (file:match("%.[a-z]+$") or file:match("%.[a-z]+%.")) then |
425 | add_all_patterns(file, patterns, files) | 421 | add_all_patterns(file, patterns, files) |
426 | else | 422 | else |
@@ -430,35 +426,26 @@ local function add_patterns_for_file(files, file, patterns) | |||
430 | add_all_patterns(matched, patterns, files) | 426 | add_all_patterns(matched, patterns, files) |
431 | end | 427 | end |
432 | end | 428 | end |
433 | table.insert(files, { #files + 1, file }) | 429 | table.insert(files, {#files + 1, file}) |
434 | end | 430 | end |
435 | end | 431 | end |
436 | 432 | ||
437 | local function check_external_dependency_at( | 433 | local function check_external_dependency_at(prefix, name, ext_files, vars, dirs, err_files, cache) |
438 | prefix, | ||
439 | name, | ||
440 | ext_files, | ||
441 | vars, | ||
442 | dirs, | ||
443 | err_files, | ||
444 | cache) | ||
445 | |||
446 | local fs = require("luarocks.fs") | 434 | local fs = require("luarocks.fs") |
447 | cache = cache or {} | 435 | cache = cache or {} |
448 | 436 | ||
449 | for dirname, dirdata in util.sortedpairs(dirs) do | 437 | for dirname, dirdata in util.sortedpairs(dirs) do |
450 | local paths | 438 | local paths |
451 | local path_var_value = vars[name .. "_" .. dirname] | 439 | local path_var_value = vars[name.."_"..dirname] |
452 | local dirdatastr = dirdata.subdir | ||
453 | if path_var_value then | 440 | if path_var_value then |
454 | paths = { path_var_value } | 441 | paths = { path_var_value } |
455 | elseif type(dirdatastr) == "table" then | 442 | elseif type(dirdata.subdir) == "table" then |
456 | paths = {} | 443 | paths = {} |
457 | for i, v in ipairs(dirdatastr) do | 444 | for i,v in ipairs(dirdata.subdir) do |
458 | paths[i] = dir.path(prefix, v) | 445 | paths[i] = dir.path(prefix, v) |
459 | end | 446 | end |
460 | else | 447 | else |
461 | paths = { dir.path(prefix, dirdatastr) } | 448 | paths = { dir.path(prefix, dirdata.subdir) } |
462 | end | 449 | end |
463 | local file_or_files = ext_files[dirdata.testfile] | 450 | local file_or_files = ext_files[dirdata.testfile] |
464 | if file_or_files then | 451 | if file_or_files then |
@@ -484,15 +471,15 @@ local function check_external_dependency_at( | |||
484 | for _, fa in ipairs(files) do | 471 | for _, fa in ipairs(files) do |
485 | 472 | ||
486 | local f = fa[2] | 473 | local f = fa[2] |
487 | 474 | -- small convenience hack | |
488 | if f:match("%.so$") or f:match("%.dylib$") or f:match("%.dll$") then | 475 | if f:match("%.so$") or f:match("%.dylib$") or f:match("%.dll$") then |
489 | f = f:gsub("%.[^.]+$", "." .. cfg.external_lib_extension) | 476 | f = f:gsub("%.[^.]+$", "."..cfg.external_lib_extension) |
490 | end | 477 | end |
491 | 478 | ||
492 | local pattern | 479 | local pattern |
493 | if f:match("%*") then | 480 | if f:match("%*") then |
494 | pattern = "^" .. f:gsub("([-.+])", "%%%1"):gsub("%*", ".*") .. "$" | 481 | pattern = "^" .. f:gsub("([-.+])", "%%%1"):gsub("%*", ".*") .. "$" |
495 | f = "matching " .. f | 482 | f = "matching "..f |
496 | end | 483 | end |
497 | 484 | ||
498 | for _, d in ipairs(paths) do | 485 | for _, d in ipairs(paths) do |
@@ -515,7 +502,7 @@ local function check_external_dependency_at( | |||
515 | dirdata.file = f | 502 | dirdata.file = f |
516 | break | 503 | break |
517 | else | 504 | else |
518 | table.insert(err_files[dirdata.testfile], f .. " in " .. d) | 505 | table.insert(err_files[dirdata.testfile], f.." in "..d) |
519 | end | 506 | end |
520 | end | 507 | end |
521 | if found then | 508 | if found then |
@@ -526,9 +513,9 @@ local function check_external_dependency_at( | |||
526 | return nil, dirname, dirdata.testfile | 513 | return nil, dirname, dirdata.testfile |
527 | end | 514 | end |
528 | else | 515 | else |
529 | 516 | -- When we have a set of subdir suffixes, look for one that exists. | |
530 | 517 | -- For these reason, we now put "lib" ahead of "" on Windows in our | |
531 | 518 | -- default set. | |
532 | dirdata.dir = paths[1] | 519 | dirdata.dir = paths[1] |
533 | for _, p in ipairs(paths) do | 520 | for _, p in ipairs(paths) do |
534 | if fs.exists(p) then | 521 | if fs.exists(p) then |
@@ -540,23 +527,18 @@ local function check_external_dependency_at( | |||
540 | end | 527 | end |
541 | 528 | ||
542 | for dirname, dirdata in pairs(dirs) do | 529 | for dirname, dirdata in pairs(dirs) do |
543 | vars[name .. "_" .. dirname] = dirdata.dir | 530 | vars[name.."_"..dirname] = dirdata.dir |
544 | vars[name .. "_" .. dirname .. "_FILE"] = dirdata.file | 531 | vars[name.."_"..dirname.."_FILE"] = dirdata.file |
545 | end | 532 | end |
546 | vars[name .. "_DIR"] = prefix | 533 | vars[name.."_DIR"] = prefix |
547 | return true | 534 | return true |
548 | end | 535 | end |
549 | 536 | ||
550 | local function check_external_dependency( | 537 | local function check_external_dependency(name, ext_files, vars, mode, cache) |
551 | name, | ||
552 | ext_files, | ||
553 | vars, | ||
554 | mode, | ||
555 | cache) | ||
556 | local ok | 538 | local ok |
557 | local err_dirname | 539 | local err_dirname |
558 | local err_testfile | 540 | local err_testfile |
559 | local err_files = { program = {}, header = {}, library = {} } | 541 | local err_files = {program = {}, header = {}, library = {}} |
560 | 542 | ||
561 | local dirs = get_external_deps_dirs(mode) | 543 | local dirs = get_external_deps_dirs(mode) |
562 | 544 | ||
@@ -590,7 +572,7 @@ local function check_external_dependency( | |||
590 | end | 572 | end |
591 | 573 | ||
592 | function deps.autodetect_external_dependencies(build) | 574 | function deps.autodetect_external_dependencies(build) |
593 | 575 | -- only applies to the 'builtin' build type | |
594 | if not build or not build.modules then | 576 | if not build or not build.modules then |
595 | return nil | 577 | return nil |
596 | end | 578 | end |
@@ -599,12 +581,9 @@ function deps.autodetect_external_dependencies(build) | |||
599 | local any = false | 581 | local any = false |
600 | for _, data in pairs(build.modules) do | 582 | for _, data in pairs(build.modules) do |
601 | if type(data) == "table" and data.libraries then | 583 | if type(data) == "table" and data.libraries then |
602 | local libraries | 584 | local libraries = data.libraries |
603 | local librariesstr = data.libraries | 585 | if type(libraries) == "string" then |
604 | if type(librariesstr) == "string" then | 586 | libraries = { libraries } |
605 | libraries = { librariesstr } | ||
606 | else | ||
607 | libraries = librariesstr | ||
608 | end | 587 | end |
609 | local incdirs = {} | 588 | local incdirs = {} |
610 | local libdirs = {} | 589 | local libdirs = {} |
@@ -626,20 +605,21 @@ function deps.autodetect_external_dependencies(build) | |||
626 | return any and extdeps or nil | 605 | return any and extdeps or nil |
627 | end | 606 | end |
628 | 607 | ||
629 | 608 | --- Set up path-related variables for external dependencies. | |
630 | 609 | -- For each key in the external_dependencies table in the | |
631 | 610 | -- rockspec file, four variables are created: <key>_DIR, <key>_BINDIR, | |
632 | 611 | -- <key>_INCDIR and <key>_LIBDIR. These are not overwritten | |
633 | 612 | -- if already set (e.g. by the LuaRocks config file or through the | |
634 | 613 | -- command-line). Values in the external_dependencies table | |
635 | 614 | -- are tables that may contain a "header" or a "library" field, | |
636 | 615 | -- with filenames to be tested for existence. | |
637 | 616 | -- @param rockspec table: The rockspec table. | |
638 | 617 | -- @param mode string: if "build" is given, checks all files; | |
639 | 618 | -- if "install" is given, do not scan for headers. | |
640 | 619 | -- @return boolean or (nil, string): True if no errors occurred, or | |
641 | 620 | -- nil and an error message if any test failed. | |
642 | function deps.check_external_deps(rockspec, mode) | 621 | function deps.check_external_deps(rockspec, mode) |
622 | assert(rockspec:type() == "rockspec") | ||
643 | 623 | ||
644 | if not rockspec.external_dependencies then | 624 | if not rockspec.external_dependencies then |
645 | rockspec.external_dependencies = deps.autodetect_external_dependencies(rockspec.build) | 625 | rockspec.external_dependencies = deps.autodetect_external_dependencies(rockspec.build) |
@@ -648,21 +628,21 @@ function deps.check_external_deps(rockspec, mode) | |||
648 | return true | 628 | return true |
649 | end | 629 | end |
650 | 630 | ||
651 | for name, ext_files in util.sortedpairs(rockspec.external_dependencies.queries) do | 631 | for name, ext_files in util.sortedpairs(rockspec.external_dependencies) do |
652 | local ok, err_dirname, err_testfile, err_files = check_external_dependency(name, ext_files, rockspec.variables, mode) | 632 | local ok, err_dirname, err_testfile, err_files = check_external_dependency(name, ext_files, rockspec.variables, mode) |
653 | if not ok then | 633 | if not ok then |
654 | local lines = { "Could not find " .. err_testfile .. " file for " .. name } | 634 | local lines = {"Could not find "..err_testfile.." file for "..name} |
655 | 635 | ||
656 | local err_paths = {} | 636 | local err_paths = {} |
657 | for _, err_file in ipairs(err_files[err_testfile]) do | 637 | for _, err_file in ipairs(err_files[err_testfile]) do |
658 | if not err_paths[err_file] then | 638 | if not err_paths[err_file] then |
659 | err_paths[err_file] = true | 639 | err_paths[err_file] = true |
660 | table.insert(lines, " No file " .. err_file) | 640 | table.insert(lines, " No file "..err_file) |
661 | end | 641 | end |
662 | end | 642 | end |
663 | 643 | ||
664 | table.insert(lines, "You may have to install " .. name .. " in your system and/or pass " .. name .. "_DIR or " .. name .. "_" .. err_dirname .. " to the luarocks command.") | 644 | table.insert(lines, "You may have to install "..name.." in your system and/or pass "..name.."_DIR or "..name.."_"..err_dirname.." to the luarocks command.") |
665 | table.insert(lines, "Example: luarocks install " .. rockspec.name .. " " .. name .. "_DIR=/usr/local") | 645 | table.insert(lines, "Example: luarocks install "..rockspec.name.." "..name.."_DIR=/usr/local") |
666 | 646 | ||
667 | return nil, table.concat(lines, "\n"), "dependency" | 647 | return nil, table.concat(lines, "\n"), "dependency" |
668 | end | 648 | end |
@@ -670,17 +650,18 @@ function deps.check_external_deps(rockspec, mode) | |||
670 | return true | 650 | return true |
671 | end | 651 | end |
672 | 652 | ||
673 | 653 | --- Recursively add satisfied dependencies of a package to a table, | |
674 | 654 | -- to build a transitive closure of all dependent packages. | |
675 | 655 | -- Additionally ensures that `dependencies` table of the manifest is up-to-date. | |
676 | 656 | -- @param results table: The results table being built, maps package names to versions. | |
677 | 657 | -- @param mdeps table: The manifest dependencies table. | |
678 | 658 | -- @param name string: Package name. | |
679 | 659 | -- @param version string: Package version. | |
680 | function deps.scan_deps(results, mdeps, name, version, deps_mode) | 660 | function deps.scan_deps(results, mdeps, name, version, deps_mode) |
681 | assert(type(results) == "table") | 661 | assert(type(results) == "table") |
682 | assert(type(mdeps) == "table") | 662 | assert(type(mdeps) == "table") |
683 | assert(not name:match("/")) | 663 | assert(type(name) == "string" and not name:match("/")) |
664 | assert(type(version) == "string") | ||
684 | 665 | ||
685 | local fetch = require("luarocks.fetch") | 666 | local fetch = require("luarocks.fetch") |
686 | 667 | ||
@@ -692,11 +673,11 @@ function deps.scan_deps(results, mdeps, name, version, deps_mode) | |||
692 | local dependencies = mdn[version] | 673 | local dependencies = mdn[version] |
693 | local rocks_provided | 674 | local rocks_provided |
694 | if not dependencies then | 675 | if not dependencies then |
695 | local rockspec = fetch.load_local_rockspec(path.rockspec_file(name, version), false) | 676 | local rockspec, err = fetch.load_local_rockspec(path.rockspec_file(name, version), false) |
696 | if not rockspec then | 677 | if not rockspec then |
697 | return | 678 | return |
698 | end | 679 | end |
699 | dependencies = rockspec.dependencies.queries | 680 | dependencies = rockspec.dependencies |
700 | rocks_provided = rockspec.rocks_provided | 681 | rocks_provided = rockspec.rocks_provided |
701 | mdn[version] = dependencies | 682 | mdn[version] = dependencies |
702 | else | 683 | else |
@@ -755,13 +736,13 @@ local function find_lua_incdir(prefix, luaver, luajitver) | |||
755 | end | 736 | end |
756 | end | 737 | end |
757 | 738 | ||
758 | 739 | -- not found, will fallback to a default | |
759 | return nil, mainerr | 740 | return nil, mainerr |
760 | end | 741 | end |
761 | 742 | ||
762 | function deps.check_lua_incdir(vars) | 743 | function deps.check_lua_incdir(vars) |
763 | if vars.LUA_INCDIR_OK == true then | 744 | if vars.LUA_INCDIR_OK == true |
764 | return true | 745 | then return true |
765 | end | 746 | end |
766 | 747 | ||
767 | local ljv = util.get_luajit_version() | 748 | local ljv = util.get_luajit_version() |
@@ -788,8 +769,8 @@ function deps.check_lua_incdir(vars) | |||
788 | end | 769 | end |
789 | 770 | ||
790 | function deps.check_lua_libdir(vars) | 771 | function deps.check_lua_libdir(vars) |
791 | if vars.LUA_LIBDIR_OK == true then | 772 | if vars.LUA_LIBDIR_OK == true |
792 | return true | 773 | then return true |
793 | end | 774 | end |
794 | 775 | ||
795 | local fs = require("luarocks.fs") | 776 | local fs = require("luarocks.fs") |
@@ -822,10 +803,10 @@ function deps.check_lua_libdir(vars) | |||
822 | local fd = io.open(filename, "r") | 803 | local fd = io.open(filename, "r") |
823 | if fd then | 804 | if fd then |
824 | if not vars.LUA_LIBDIR_FILE:match((cfg.lua_version:gsub("%.", "%%.?"))) then | 805 | if not vars.LUA_LIBDIR_FILE:match((cfg.lua_version:gsub("%.", "%%.?"))) then |
825 | 806 | -- if filename isn't versioned, check file contents | |
826 | local txt = fd:read("*a") | 807 | local txt = fd:read("*a") |
827 | ok = txt:find("Lua " .. cfg.lua_version, 1, true) or | 808 | ok = txt:match("Lua " .. cfg.lua_version, 1, true) |
828 | txt:find("lua" .. (cfg.lua_version:gsub("%.", "")), 1, true) | 809 | or txt:match("lua" .. (cfg.lua_version:gsub("%.", "")), 1, true) |
829 | if not ok then | 810 | if not ok then |
830 | err = "Lua library at " .. filename .. " does not match Lua version " .. cfg.lua_version .. ". You can use `luarocks config variables.LUA_LIBDIR <path>` to set the correct location." | 811 | err = "Lua library at " .. filename .. " does not match Lua version " .. cfg.lua_version .. ". You can use `luarocks config variables.LUA_LIBDIR <path>` to set the correct location." |
831 | end | 812 | end |
diff --git a/src/luarocks/deps.tl b/src/luarocks/deps.tl index dca855eb..d66ed4e8 100644 --- a/src/luarocks/deps.tl +++ b/src/luarocks/deps.tl | |||
@@ -696,7 +696,7 @@ function deps.scan_deps(results: {string: string}, mdeps: {string: {string: {Que | |||
696 | if not rockspec then | 696 | if not rockspec then |
697 | return | 697 | return |
698 | end | 698 | end |
699 | dependencies = rockspec.dependencies.queries | 699 | dependencies = rockspec.dependencies |
700 | rocks_provided = rockspec.rocks_provided | 700 | rocks_provided = rockspec.rocks_provided |
701 | mdn[version] = dependencies | 701 | mdn[version] = dependencies |
702 | else | 702 | else |
diff --git a/src/luarocks/rockspecs-original.lua b/src/luarocks/rockspecs-original.lua new file mode 100644 index 00000000..454bab77 --- /dev/null +++ b/src/luarocks/rockspecs-original.lua | |||
@@ -0,0 +1,183 @@ | |||
1 | local rockspecs = {} | ||
2 | |||
3 | local cfg = require("luarocks.core.cfg") | ||
4 | local dir = require("luarocks.dir") | ||
5 | local path = require("luarocks.path") | ||
6 | local queries = require("luarocks.queries") | ||
7 | local type_rockspec = require("luarocks.type.rockspec") | ||
8 | local util = require("luarocks.util") | ||
9 | local vers = require("luarocks.core.vers") | ||
10 | |||
11 | local vendored_build_type_set = { | ||
12 | ["builtin"] = true, | ||
13 | ["cmake"] = true, | ||
14 | ["command"] = true, | ||
15 | ["make"] = true, | ||
16 | ["module"] = true, -- compatibility alias | ||
17 | ["none"] = true, | ||
18 | } | ||
19 | |||
20 | local rockspec_mt = {} | ||
21 | |||
22 | rockspec_mt.__index = rockspec_mt | ||
23 | |||
24 | function rockspec_mt.type() | ||
25 | return "rockspec" | ||
26 | end | ||
27 | |||
28 | --- Perform platform-specific overrides on a table. | ||
29 | -- Overrides values of table with the contents of the appropriate | ||
30 | -- subset of its "platforms" field. The "platforms" field should | ||
31 | -- be a table containing subtables keyed with strings representing | ||
32 | -- platform names. Names that match the contents of the global | ||
33 | -- detected platforms setting are used. For example, if | ||
34 | -- platform "unix" is detected, then the fields of | ||
35 | -- tbl.platforms.unix will overwrite those of tbl with the same | ||
36 | -- names. For table values, the operation is performed recursively | ||
37 | -- (tbl.platforms.foo.x.y.z overrides tbl.x.y.z; other contents of | ||
38 | -- tbl.x are preserved). | ||
39 | -- @param tbl table or nil: Table which may contain a "platforms" field; | ||
40 | -- if it doesn't (or if nil is passed), this function does nothing. | ||
41 | local function platform_overrides(tbl) | ||
42 | assert(type(tbl) == "table" or not tbl) | ||
43 | |||
44 | if not tbl then return end | ||
45 | |||
46 | if tbl.platforms then | ||
47 | for platform in cfg.each_platform() do | ||
48 | local platform_tbl = tbl.platforms[platform] | ||
49 | if platform_tbl then | ||
50 | util.deep_merge(tbl, platform_tbl) | ||
51 | end | ||
52 | end | ||
53 | end | ||
54 | tbl.platforms = nil | ||
55 | end | ||
56 | |||
57 | local function convert_dependencies(rockspec, key) | ||
58 | if rockspec[key] then | ||
59 | for i = 1, #rockspec[key] do | ||
60 | local parsed, err = queries.from_dep_string(rockspec[key][i]) | ||
61 | if not parsed then | ||
62 | return nil, "Parse error processing dependency '"..rockspec[key][i].."': "..tostring(err) | ||
63 | end | ||
64 | rockspec[key][i] = parsed | ||
65 | end | ||
66 | else | ||
67 | rockspec[key] = {} | ||
68 | end | ||
69 | return true | ||
70 | end | ||
71 | |||
72 | --- Set up path-related variables for a given rock. | ||
73 | -- Create a "variables" table in the rockspec table, containing | ||
74 | -- adjusted variables according to the configuration file. | ||
75 | -- @param rockspec table: The rockspec table. | ||
76 | local function configure_paths(rockspec) | ||
77 | local vars = {} | ||
78 | for k,v in pairs(cfg.variables) do | ||
79 | vars[k] = v | ||
80 | end | ||
81 | local name, version = rockspec.name, rockspec.version | ||
82 | vars.PREFIX = path.install_dir(name, version) | ||
83 | vars.LUADIR = path.lua_dir(name, version) | ||
84 | vars.LIBDIR = path.lib_dir(name, version) | ||
85 | vars.CONFDIR = path.conf_dir(name, version) | ||
86 | vars.BINDIR = path.bin_dir(name, version) | ||
87 | vars.DOCDIR = path.doc_dir(name, version) | ||
88 | rockspec.variables = vars | ||
89 | end | ||
90 | |||
91 | function rockspecs.from_persisted_table(filename, rockspec, globals, quick) | ||
92 | assert(type(rockspec) == "table") | ||
93 | assert(type(globals) == "table" or globals == nil) | ||
94 | assert(type(filename) == "string") | ||
95 | assert(type(quick) == "boolean" or quick == nil) | ||
96 | |||
97 | if rockspec.rockspec_format then | ||
98 | if vers.compare_versions(rockspec.rockspec_format, type_rockspec.rockspec_format) then | ||
99 | return nil, "Rockspec format "..rockspec.rockspec_format.." is not supported, please upgrade LuaRocks." | ||
100 | end | ||
101 | end | ||
102 | |||
103 | if not quick then | ||
104 | local ok, err = type_rockspec.check(rockspec, globals or {}) | ||
105 | if not ok then | ||
106 | return nil, err | ||
107 | end | ||
108 | end | ||
109 | |||
110 | --- Check if rockspec format version satisfies version requirement. | ||
111 | -- @param rockspec table: The rockspec table. | ||
112 | -- @param version string: required version. | ||
113 | -- @return boolean: true if rockspec format matches version or is newer, false otherwise. | ||
114 | do | ||
115 | local parsed_format = vers.parse_version(rockspec.rockspec_format or "1.0") | ||
116 | rockspec.format_is_at_least = function(self, version) | ||
117 | return parsed_format >= vers.parse_version(version) | ||
118 | end | ||
119 | end | ||
120 | |||
121 | platform_overrides(rockspec.build) | ||
122 | platform_overrides(rockspec.dependencies) | ||
123 | platform_overrides(rockspec.build_dependencies) | ||
124 | platform_overrides(rockspec.test_dependencies) | ||
125 | platform_overrides(rockspec.external_dependencies) | ||
126 | platform_overrides(rockspec.source) | ||
127 | platform_overrides(rockspec.hooks) | ||
128 | platform_overrides(rockspec.test) | ||
129 | |||
130 | rockspec.name = rockspec.package:lower() | ||
131 | |||
132 | local protocol, pathname = dir.split_url(rockspec.source.url) | ||
133 | if dir.is_basic_protocol(protocol) then | ||
134 | rockspec.source.file = rockspec.source.file or dir.base_name(rockspec.source.url) | ||
135 | end | ||
136 | rockspec.source.protocol, rockspec.source.pathname = protocol, pathname | ||
137 | |||
138 | -- Temporary compatibility | ||
139 | if rockspec.source.cvs_module then rockspec.source.module = rockspec.source.cvs_module end | ||
140 | if rockspec.source.cvs_tag then rockspec.source.tag = rockspec.source.cvs_tag end | ||
141 | |||
142 | rockspec.local_abs_filename = filename | ||
143 | rockspec.source.dir_set = rockspec.source.dir ~= nil | ||
144 | rockspec.source.dir = rockspec.source.dir or rockspec.source.module | ||
145 | |||
146 | rockspec.rocks_provided = util.get_rocks_provided(rockspec) | ||
147 | |||
148 | for _, key in ipairs({"dependencies", "build_dependencies", "test_dependencies"}) do | ||
149 | local ok, err = convert_dependencies(rockspec, key) | ||
150 | if not ok then | ||
151 | return nil, err | ||
152 | end | ||
153 | end | ||
154 | |||
155 | if rockspec.build | ||
156 | and rockspec.build.type | ||
157 | and not vendored_build_type_set[rockspec.build.type] then | ||
158 | local build_pkg_name = "luarocks-build-" .. rockspec.build.type | ||
159 | if not rockspec.build_dependencies then | ||
160 | rockspec.build_dependencies = {} | ||
161 | end | ||
162 | |||
163 | local found = false | ||
164 | for _, dep in ipairs(rockspec.build_dependencies) do | ||
165 | if dep.name == build_pkg_name then | ||
166 | found = true | ||
167 | break | ||
168 | end | ||
169 | end | ||
170 | |||
171 | if not found then | ||
172 | table.insert(rockspec.build_dependencies, queries.from_dep_string(build_pkg_name)) | ||
173 | end | ||
174 | end | ||
175 | |||
176 | if not quick then | ||
177 | configure_paths(rockspec) | ||
178 | end | ||
179 | |||
180 | return setmetatable(rockspec, rockspec_mt) | ||
181 | end | ||
182 | |||
183 | return rockspecs | ||
diff --git a/src/luarocks/rockspecs.lua b/src/luarocks/rockspecs.lua index 454bab77..2910ccf9 100644 --- a/src/luarocks/rockspecs.lua +++ b/src/luarocks/rockspecs.lua | |||
@@ -1,5 +1,7 @@ | |||
1 | local _tl_compat; if (tonumber((_VERSION or ''):match('[%d.]*$')) or 0) < 5.3 then local p, m = pcall(require, 'compat53.module'); if p then _tl_compat = m end end; local ipairs = _tl_compat and _tl_compat.ipairs or ipairs; local pairs = _tl_compat and _tl_compat.pairs or pairs; local table = _tl_compat and _tl_compat.table or table | ||
1 | local rockspecs = {} | 2 | local rockspecs = {} |
2 | 3 | ||
4 | |||
3 | local cfg = require("luarocks.core.cfg") | 5 | local cfg = require("luarocks.core.cfg") |
4 | local dir = require("luarocks.dir") | 6 | local dir = require("luarocks.dir") |
5 | local path = require("luarocks.path") | 7 | local path = require("luarocks.path") |
@@ -8,45 +10,53 @@ local type_rockspec = require("luarocks.type.rockspec") | |||
8 | local util = require("luarocks.util") | 10 | local util = require("luarocks.util") |
9 | local vers = require("luarocks.core.vers") | 11 | local vers = require("luarocks.core.vers") |
10 | 12 | ||
13 | local rockspec = require("luarocks.core.types.rockspec") | ||
14 | |||
15 | |||
16 | |||
17 | |||
18 | |||
19 | |||
11 | local vendored_build_type_set = { | 20 | local vendored_build_type_set = { |
12 | ["builtin"] = true, | 21 | ["builtin"] = true, |
13 | ["cmake"] = true, | 22 | ["cmake"] = true, |
14 | ["command"] = true, | 23 | ["command"] = true, |
15 | ["make"] = true, | 24 | ["make"] = true, |
16 | ["module"] = true, -- compatibility alias | 25 | ["module"] = true, |
17 | ["none"] = true, | 26 | ["none"] = true, |
18 | } | 27 | } |
19 | 28 | ||
20 | local rockspec_mt = {} | 29 | local rockspec_mt = {} |
21 | 30 | ||
22 | rockspec_mt.__index = rockspec_mt | 31 | rockspec_mt.__index = rockspec.Rockspec |
23 | 32 | ||
24 | function rockspec_mt.type() | 33 | function rockspec.Rockspec.type() |
25 | return "rockspec" | 34 | return "rockspec" |
26 | end | 35 | end |
27 | 36 | ||
28 | --- Perform platform-specific overrides on a table. | 37 | |
29 | -- Overrides values of table with the contents of the appropriate | 38 | |
30 | -- subset of its "platforms" field. The "platforms" field should | 39 | |
31 | -- be a table containing subtables keyed with strings representing | 40 | |
32 | -- platform names. Names that match the contents of the global | 41 | |
33 | -- detected platforms setting are used. For example, if | 42 | |
34 | -- platform "unix" is detected, then the fields of | 43 | |
35 | -- tbl.platforms.unix will overwrite those of tbl with the same | 44 | |
36 | -- names. For table values, the operation is performed recursively | 45 | |
37 | -- (tbl.platforms.foo.x.y.z overrides tbl.x.y.z; other contents of | 46 | |
38 | -- tbl.x are preserved). | 47 | |
39 | -- @param tbl table or nil: Table which may contain a "platforms" field; | 48 | |
40 | -- if it doesn't (or if nil is passed), this function does nothing. | 49 | |
41 | local function platform_overrides(tbl) | 50 | local function platform_overrides(tbl) |
42 | assert(type(tbl) == "table" or not tbl) | ||
43 | 51 | ||
44 | if not tbl then return end | 52 | if not tbl then return end |
45 | 53 | ||
46 | if tbl.platforms then | 54 | local tblp = tbl.platforms |
55 | |||
56 | if type(tblp) == "table" then | ||
47 | for platform in cfg.each_platform() do | 57 | for platform in cfg.each_platform() do |
48 | local platform_tbl = tbl.platforms[platform] | 58 | local platform_tbl = tblp[platform] |
49 | if platform_tbl then | 59 | if type(platform_tbl) == "table" then |
50 | util.deep_merge(tbl, platform_tbl) | 60 | util.deep_merge(tbl, platform_tbl) |
51 | end | 61 | end |
52 | end | 62 | end |
@@ -54,28 +64,28 @@ local function platform_overrides(tbl) | |||
54 | tbl.platforms = nil | 64 | tbl.platforms = nil |
55 | end | 65 | end |
56 | 66 | ||
57 | local function convert_dependencies(rockspec, key) | 67 | local function convert_dependencies(dependencies) |
58 | if rockspec[key] then | 68 | if not dependencies then |
59 | for i = 1, #rockspec[key] do | 69 | return {} |
60 | local parsed, err = queries.from_dep_string(rockspec[key][i]) | 70 | end |
61 | if not parsed then | 71 | local qs = {} |
62 | return nil, "Parse error processing dependency '"..rockspec[key][i].."': "..tostring(err) | 72 | for i = 1, #dependencies do |
63 | end | 73 | local parsed, err = queries.from_dep_string(dependencies[i]) |
64 | rockspec[key][i] = parsed | 74 | if not parsed then |
75 | return nil, "Parse error processing dependency '" .. dependencies[i] .. "': " .. tostring(err) | ||
65 | end | 76 | end |
66 | else | 77 | qs[i] = parsed |
67 | rockspec[key] = {} | ||
68 | end | 78 | end |
69 | return true | 79 | return qs |
70 | end | 80 | end |
71 | 81 | ||
72 | --- Set up path-related variables for a given rock. | 82 | |
73 | -- Create a "variables" table in the rockspec table, containing | 83 | |
74 | -- adjusted variables according to the configuration file. | 84 | |
75 | -- @param rockspec table: The rockspec table. | 85 | |
76 | local function configure_paths(rockspec) | 86 | local function configure_paths(rockspec) |
77 | local vars = {} | 87 | local vars = {} |
78 | for k,v in pairs(cfg.variables) do | 88 | for k, v in pairs(cfg.variables) do |
79 | vars[k] = v | 89 | vars[k] = v |
80 | end | 90 | end |
81 | local name, version = rockspec.name, rockspec.version | 91 | local name, version = rockspec.name, rockspec.version |
@@ -89,14 +99,10 @@ local function configure_paths(rockspec) | |||
89 | end | 99 | end |
90 | 100 | ||
91 | function rockspecs.from_persisted_table(filename, rockspec, globals, quick) | 101 | function rockspecs.from_persisted_table(filename, rockspec, globals, quick) |
92 | assert(type(rockspec) == "table") | ||
93 | assert(type(globals) == "table" or globals == nil) | ||
94 | assert(type(filename) == "string") | ||
95 | assert(type(quick) == "boolean" or quick == nil) | ||
96 | 102 | ||
97 | if rockspec.rockspec_format then | 103 | if rockspec.rockspec_format then |
98 | if vers.compare_versions(rockspec.rockspec_format, type_rockspec.rockspec_format) then | 104 | if vers.compare_versions(rockspec.rockspec_format, type_rockspec.rockspec_format) then |
99 | return nil, "Rockspec format "..rockspec.rockspec_format.." is not supported, please upgrade LuaRocks." | 105 | return nil, "Rockspec format " .. rockspec.rockspec_format .. " is not supported, please upgrade LuaRocks." |
100 | end | 106 | end |
101 | end | 107 | end |
102 | 108 | ||
@@ -107,10 +113,10 @@ function rockspecs.from_persisted_table(filename, rockspec, globals, quick) | |||
107 | end | 113 | end |
108 | end | 114 | end |
109 | 115 | ||
110 | --- Check if rockspec format version satisfies version requirement. | 116 | |
111 | -- @param rockspec table: The rockspec table. | 117 | |
112 | -- @param version string: required version. | 118 | |
113 | -- @return boolean: true if rockspec format matches version or is newer, false otherwise. | 119 | |
114 | do | 120 | do |
115 | local parsed_format = vers.parse_version(rockspec.rockspec_format or "1.0") | 121 | local parsed_format = vers.parse_version(rockspec.rockspec_format or "1.0") |
116 | rockspec.format_is_at_least = function(self, version) | 122 | rockspec.format_is_at_least = function(self, version) |
@@ -135,7 +141,7 @@ function rockspecs.from_persisted_table(filename, rockspec, globals, quick) | |||
135 | end | 141 | end |
136 | rockspec.source.protocol, rockspec.source.pathname = protocol, pathname | 142 | rockspec.source.protocol, rockspec.source.pathname = protocol, pathname |
137 | 143 | ||
138 | -- Temporary compatibility | 144 | |
139 | if rockspec.source.cvs_module then rockspec.source.module = rockspec.source.cvs_module end | 145 | if rockspec.source.cvs_module then rockspec.source.module = rockspec.source.cvs_module end |
140 | if rockspec.source.cvs_tag then rockspec.source.tag = rockspec.source.cvs_tag end | 146 | if rockspec.source.cvs_tag then rockspec.source.tag = rockspec.source.cvs_tag end |
141 | 147 | ||
@@ -145,23 +151,32 @@ function rockspecs.from_persisted_table(filename, rockspec, globals, quick) | |||
145 | 151 | ||
146 | rockspec.rocks_provided = util.get_rocks_provided(rockspec) | 152 | rockspec.rocks_provided = util.get_rocks_provided(rockspec) |
147 | 153 | ||
148 | for _, key in ipairs({"dependencies", "build_dependencies", "test_dependencies"}) do | 154 | local err |
149 | local ok, err = convert_dependencies(rockspec, key) | 155 | rockspec.dependencies.queries, err = convert_dependencies(rockspec.dependencies) |
150 | if not ok then | 156 | if err then |
151 | return nil, err | 157 | return nil, err |
152 | end | ||
153 | end | 158 | end |
154 | 159 | ||
155 | if rockspec.build | 160 | rockspec.build_dependencies.queries, err = convert_dependencies(rockspec.build_dependencies) |
156 | and rockspec.build.type | 161 | if err then |
157 | and not vendored_build_type_set[rockspec.build.type] then | 162 | return nil, err |
163 | end | ||
164 | |||
165 | rockspec.test_dependencies.queries, err = convert_dependencies(rockspec.test_dependencies) | ||
166 | if err then | ||
167 | return nil, err | ||
168 | end | ||
169 | |||
170 | if rockspec.build and | ||
171 | rockspec.build.type and | ||
172 | not vendored_build_type_set[rockspec.build.type] then | ||
158 | local build_pkg_name = "luarocks-build-" .. rockspec.build.type | 173 | local build_pkg_name = "luarocks-build-" .. rockspec.build.type |
159 | if not rockspec.build_dependencies then | 174 | if not rockspec.build_dependencies then |
160 | rockspec.build_dependencies = {} | 175 | rockspec.build_dependencies = {} |
161 | end | 176 | end |
162 | 177 | ||
163 | local found = false | 178 | local found = false |
164 | for _, dep in ipairs(rockspec.build_dependencies) do | 179 | for _, dep in ipairs(rockspec.build_dependencies.queries) do |
165 | if dep.name == build_pkg_name then | 180 | if dep.name == build_pkg_name then |
166 | found = true | 181 | found = true |
167 | break | 182 | break |
@@ -169,7 +184,11 @@ function rockspecs.from_persisted_table(filename, rockspec, globals, quick) | |||
169 | end | 184 | end |
170 | 185 | ||
171 | if not found then | 186 | if not found then |
172 | table.insert(rockspec.build_dependencies, queries.from_dep_string(build_pkg_name)) | 187 | local query, errfromdep = queries.from_dep_string(build_pkg_name) |
188 | if errfromdep then | ||
189 | return nil, "Invalid dependency in rockspec: " .. err | ||
190 | end | ||
191 | table.insert(rockspec.build_dependencies.queries, query) | ||
173 | end | 192 | end |
174 | end | 193 | end |
175 | 194 | ||
diff --git a/src/luarocks/rockspecs.tl b/src/luarocks/rockspecs.tl index b65227da..c391f1e7 100644 --- a/src/luarocks/rockspecs.tl +++ b/src/luarocks/rockspecs.tl | |||
@@ -10,9 +10,9 @@ local type_rockspec = require("luarocks.type.rockspec") | |||
10 | local util = require("luarocks.util") | 10 | local util = require("luarocks.util") |
11 | local vers = require("luarocks.core.vers") | 11 | local vers = require("luarocks.core.vers") |
12 | 12 | ||
13 | local type r = require("luarocks.core.types.rockspec") | 13 | local rockspec = require("luarocks.core.types.rockspec") |
14 | local type Rockspec = r.Rockspec | 14 | local type Rockspec = rockspec.Rockspec |
15 | local type Variables = r.Variables | 15 | local type Variables = rockspec.Variables |
16 | 16 | ||
17 | local type q = require("luarocks.core.types.query") | 17 | local type q = require("luarocks.core.types.query") |
18 | local type Query = q.Query | 18 | local type Query = q.Query |
@@ -28,9 +28,9 @@ local vendored_build_type_set: {string: boolean} = { | |||
28 | 28 | ||
29 | local rockspec_mt: metatable<Rockspec> = {} | 29 | local rockspec_mt: metatable<Rockspec> = {} |
30 | 30 | ||
31 | rockspec_mt.__index = r.Rockspec | 31 | rockspec_mt.__index = rockspec.Rockspec |
32 | 32 | ||
33 | function r.Rockspec.type(): string | 33 | function rockspec.Rockspec.type(): string |
34 | return "rockspec" | 34 | return "rockspec" |
35 | end | 35 | end |
36 | 36 | ||