diff options
author | Hisham Muhammad <hisham@gobolinux.org> | 2017-09-13 12:46:22 -0300 |
---|---|---|
committer | Hisham Muhammad <hisham@gobolinux.org> | 2017-09-13 12:46:22 -0300 |
commit | f1473f71235bb89555dea7041b536144d32bac8c (patch) | |
tree | 5c0b9215801ea1711c7919c1b42085d1b5687075 /src | |
parent | 1eb598706f9000361f0059a303c3cf99be5a8ceb (diff) | |
parent | 9c853b1e7ec0f30e0e539fb56d7c81edbe5c8d7d (diff) | |
download | luarocks-f1473f71235bb89555dea7041b536144d32bac8c.tar.gz luarocks-f1473f71235bb89555dea7041b536144d32bac8c.tar.bz2 luarocks-f1473f71235bb89555dea7041b536144d32bac8c.zip |
Merge branch 'luarocks-3'
Diffstat (limited to 'src')
67 files changed, 2403 insertions, 2267 deletions
diff --git a/src/bin/luarocks b/src/bin/luarocks index be6c2b81..88a1d1ca 100755 --- a/src/bin/luarocks +++ b/src/bin/luarocks | |||
@@ -1,7 +1,7 @@ | |||
1 | #!/usr/bin/env lua | 1 | #!/usr/bin/env lua |
2 | 2 | ||
3 | -- this should be loaded first. | 3 | -- this should be loaded first. |
4 | local cfg = require("luarocks.cfg") | 4 | local cfg = require("luarocks.core.cfg") |
5 | 5 | ||
6 | local loader = require("luarocks.loader") | 6 | local loader = require("luarocks.loader") |
7 | local command_line = require("luarocks.command_line") | 7 | local command_line = require("luarocks.command_line") |
@@ -9,25 +9,25 @@ local command_line = require("luarocks.command_line") | |||
9 | program_description = "LuaRocks main command-line interface" | 9 | program_description = "LuaRocks main command-line interface" |
10 | 10 | ||
11 | commands = { | 11 | commands = { |
12 | help = "luarocks.help", | 12 | help = "luarocks.cmd.help", |
13 | pack = "luarocks.pack", | 13 | pack = "luarocks.cmd.pack", |
14 | unpack = "luarocks.unpack", | 14 | unpack = "luarocks.cmd.unpack", |
15 | build = "luarocks.build", | 15 | build = "luarocks.cmd.build", |
16 | install = "luarocks.install", | 16 | install = "luarocks.cmd.install", |
17 | search = "luarocks.search", | 17 | search = "luarocks.cmd.search", |
18 | list = "luarocks.list", | 18 | list = "luarocks.cmd.list", |
19 | remove = "luarocks.remove", | 19 | remove = "luarocks.cmd.remove", |
20 | make = "luarocks.make", | 20 | make = "luarocks.cmd.make", |
21 | download = "luarocks.download", | 21 | download = "luarocks.cmd.download", |
22 | path = "luarocks.path_cmd", | 22 | path = "luarocks.cmd.path", |
23 | show = "luarocks.show", | 23 | show = "luarocks.cmd.show", |
24 | new_version = "luarocks.new_version", | 24 | new_version = "luarocks.cmd.new_version", |
25 | lint = "luarocks.lint", | 25 | lint = "luarocks.cmd.lint", |
26 | write_rockspec = "luarocks.write_rockspec", | 26 | write_rockspec = "luarocks.cmd.write_rockspec", |
27 | purge = "luarocks.purge", | 27 | purge = "luarocks.cmd.purge", |
28 | doc = "luarocks.doc", | 28 | doc = "luarocks.cmd.doc", |
29 | upload = "luarocks.upload", | 29 | upload = "luarocks.cmd.upload", |
30 | config = "luarocks.config_cmd", | 30 | config = "luarocks.cmd.config", |
31 | } | 31 | } |
32 | 32 | ||
33 | command_line.run_command(...) | 33 | command_line.run_command(...) |
diff --git a/src/bin/luarocks-admin b/src/bin/luarocks-admin index 2890d1f1..5db24640 100755 --- a/src/bin/luarocks-admin +++ b/src/bin/luarocks-admin | |||
@@ -1,7 +1,7 @@ | |||
1 | #!/usr/bin/env lua | 1 | #!/usr/bin/env lua |
2 | 2 | ||
3 | -- this should be loaded first. | 3 | -- this should be loaded first. |
4 | local cfg = require("luarocks.cfg") | 4 | local cfg = require("luarocks.core.cfg") |
5 | 5 | ||
6 | local loader = require("luarocks.loader") | 6 | local loader = require("luarocks.loader") |
7 | local command_line = require("luarocks.command_line") | 7 | local command_line = require("luarocks.command_line") |
@@ -9,11 +9,11 @@ local command_line = require("luarocks.command_line") | |||
9 | program_description = "LuaRocks repository administration interface" | 9 | program_description = "LuaRocks repository administration interface" |
10 | 10 | ||
11 | commands = { | 11 | commands = { |
12 | help = "luarocks.help", | 12 | help = "luarocks.cmd.help", |
13 | make_manifest = "luarocks.make_manifest", | 13 | make_manifest = "luarocks.admin.cmd.make_manifest", |
14 | add = "luarocks.add", | 14 | add = "luarocks.admin.cmd.add", |
15 | remove = "luarocks.admin_remove", | 15 | remove = "luarocks.admin.cmd.remove", |
16 | refresh_cache = "luarocks.refresh_cache", | 16 | refresh_cache = "luarocks.admin.cmd.refresh_cache", |
17 | } | 17 | } |
18 | 18 | ||
19 | command_line.run_command(...) | 19 | command_line.run_command(...) |
diff --git a/src/luarocks/cache.lua b/src/luarocks/admin/cache.lua index 4a95f70e..0daa0fc0 100644 --- a/src/luarocks/cache.lua +++ b/src/luarocks/admin/cache.lua | |||
@@ -2,10 +2,9 @@ | |||
2 | --- Module handling the LuaRocks local cache. | 2 | --- Module handling the LuaRocks local cache. |
3 | -- Adds a rock or rockspec to a rocks server. | 3 | -- Adds a rock or rockspec to a rocks server. |
4 | local cache = {} | 4 | local cache = {} |
5 | package.loaded["luarocks.cache"] = cache | ||
6 | 5 | ||
7 | local fs = require("luarocks.fs") | 6 | local fs = require("luarocks.fs") |
8 | local cfg = require("luarocks.cfg") | 7 | local cfg = require("luarocks.core.cfg") |
9 | local dir = require("luarocks.dir") | 8 | local dir = require("luarocks.dir") |
10 | local util = require("luarocks.util") | 9 | local util = require("luarocks.util") |
11 | 10 | ||
diff --git a/src/luarocks/add.lua b/src/luarocks/admin/cmd/add.lua index f37d334d..daf46c1d 100644 --- a/src/luarocks/add.lua +++ b/src/luarocks/admin/cmd/add.lua | |||
@@ -2,17 +2,15 @@ | |||
2 | --- Module implementing the luarocks-admin "add" command. | 2 | --- Module implementing the luarocks-admin "add" command. |
3 | -- Adds a rock or rockspec to a rocks server. | 3 | -- Adds a rock or rockspec to a rocks server. |
4 | local add = {} | 4 | local add = {} |
5 | package.loaded["luarocks.add"] = add | ||
6 | 5 | ||
7 | local cfg = require("luarocks.cfg") | 6 | local cfg = require("luarocks.core.cfg") |
8 | local util = require("luarocks.util") | 7 | local util = require("luarocks.util") |
9 | local dir = require("luarocks.dir") | 8 | local dir = require("luarocks.dir") |
10 | local manif = require("luarocks.manif") | 9 | local writer = require("luarocks.manif.writer") |
11 | local index = require("luarocks.index") | 10 | local index = require("luarocks.index") |
12 | local fs = require("luarocks.fs") | 11 | local fs = require("luarocks.fs") |
13 | local cache = require("luarocks.cache") | 12 | local cache = require("luarocks.admin.cache") |
14 | 13 | ||
15 | util.add_run_function(add) | ||
16 | add.help_summary = "Add a rock or rockspec to a rocks server." | 14 | add.help_summary = "Add a rock or rockspec to a rocks server." |
17 | add.help_arguments = "[--server=<server>] [--no-refresh] {<rockspec>|<rock>...}" | 15 | add.help_arguments = "[--server=<server>] [--no-refresh] {<rockspec>|<rock>...}" |
18 | add.help = [[ | 16 | add.help = [[ |
@@ -24,6 +22,15 @@ The flag --no-refresh indicates the local cache should not be refreshed | |||
24 | prior to generation of the updated manifest. | 22 | prior to generation of the updated manifest. |
25 | ]] | 23 | ]] |
26 | 24 | ||
25 | local function zip_manifests() | ||
26 | for ver in util.lua_versions() do | ||
27 | local file = "manifest-"..ver | ||
28 | local zip = file..".zip" | ||
29 | fs.delete(dir.path(fs.current_dir(), zip)) | ||
30 | fs.zip(zip, file) | ||
31 | end | ||
32 | end | ||
33 | |||
27 | local function add_files_to_server(refresh, rockfiles, server, upload_server) | 34 | local function add_files_to_server(refresh, rockfiles, server, upload_server) |
28 | assert(type(refresh) == "boolean" or not refresh) | 35 | assert(type(refresh) == "boolean" or not refresh) |
29 | assert(type(rockfiles) == "table") | 36 | assert(type(rockfiles) == "table") |
@@ -68,9 +75,9 @@ local function add_files_to_server(refresh, rockfiles, server, upload_server) | |||
68 | if not ok then return nil, err end | 75 | if not ok then return nil, err end |
69 | 76 | ||
70 | util.printout("Updating manifest...") | 77 | util.printout("Updating manifest...") |
71 | manif.make_manifest(local_cache, "one", true) | 78 | writer.make_manifest(local_cache, "one", true) |
72 | 79 | ||
73 | manif.zip_manifests() | 80 | zip_manifests() |
74 | 81 | ||
75 | util.printout("Updating index.html...") | 82 | util.printout("Updating index.html...") |
76 | index.make_index(local_cache) | 83 | index.make_index(local_cache) |
diff --git a/src/luarocks/make_manifest.lua b/src/luarocks/admin/cmd/make_manifest.lua index c39c2939..57851942 100644 --- a/src/luarocks/make_manifest.lua +++ b/src/luarocks/admin/cmd/make_manifest.lua | |||
@@ -2,17 +2,15 @@ | |||
2 | --- Module implementing the luarocks-admin "make_manifest" command. | 2 | --- Module implementing the luarocks-admin "make_manifest" command. |
3 | -- Compile a manifest file for a repository. | 3 | -- Compile a manifest file for a repository. |
4 | local make_manifest = {} | 4 | local make_manifest = {} |
5 | package.loaded["luarocks.make_manifest"] = make_manifest | ||
6 | 5 | ||
7 | local manif = require("luarocks.manif") | 6 | local writer = require("luarocks.manif.writer") |
8 | local index = require("luarocks.index") | 7 | local index = require("luarocks.index") |
9 | local cfg = require("luarocks.cfg") | 8 | local cfg = require("luarocks.core.cfg") |
10 | local util = require("luarocks.util") | 9 | local util = require("luarocks.util") |
11 | local deps = require("luarocks.deps") | 10 | local deps = require("luarocks.deps") |
12 | local fs = require("luarocks.fs") | 11 | local fs = require("luarocks.fs") |
13 | local dir = require("luarocks.dir") | 12 | local dir = require("luarocks.dir") |
14 | 13 | ||
15 | util.add_run_function(make_manifest) | ||
16 | make_manifest.help_summary = "Compile a manifest file for a repository." | 14 | make_manifest.help_summary = "Compile a manifest file for a repository." |
17 | 15 | ||
18 | make_manifest.help = [[ | 16 | make_manifest.help = [[ |
@@ -37,7 +35,7 @@ function make_manifest.command(flags, repo) | |||
37 | util.warning("This looks like a local rocks tree, but you did not pass --local-tree.") | 35 | util.warning("This looks like a local rocks tree, but you did not pass --local-tree.") |
38 | end | 36 | end |
39 | 37 | ||
40 | local ok, err = manif.make_manifest(repo, deps.get_deps_mode(flags), not flags["local-tree"]) | 38 | local ok, err = writer.make_manifest(repo, deps.get_deps_mode(flags), not flags["local-tree"]) |
41 | if ok and not flags["local-tree"] then | 39 | if ok and not flags["local-tree"] then |
42 | util.printout("Generating index.html for "..repo) | 40 | util.printout("Generating index.html for "..repo) |
43 | index.make_index(repo) | 41 | index.make_index(repo) |
diff --git a/src/luarocks/refresh_cache.lua b/src/luarocks/admin/cmd/refresh_cache.lua index bbfd1f4d..947dbfb0 100644 --- a/src/luarocks/refresh_cache.lua +++ b/src/luarocks/admin/cmd/refresh_cache.lua | |||
@@ -1,13 +1,10 @@ | |||
1 | 1 | ||
2 | --- Module implementing the luarocks-admin "refresh_cache" command. | 2 | --- Module implementing the luarocks-admin "refresh_cache" command. |
3 | local refresh_cache = {} | 3 | local refresh_cache = {} |
4 | package.loaded["luarocks.refresh_cache"] = refresh_cache | ||
5 | 4 | ||
6 | local util = require("luarocks.util") | 5 | local cfg = require("luarocks.core.cfg") |
7 | local cfg = require("luarocks.cfg") | 6 | local cache = require("luarocks.admin.cache") |
8 | local cache = require("luarocks.cache") | ||
9 | 7 | ||
10 | util.add_run_function(refresh_cache) | ||
11 | refresh_cache.help_summary = "Refresh local cache of a remote rocks server." | 8 | refresh_cache.help_summary = "Refresh local cache of a remote rocks server." |
12 | refresh_cache.help_arguments = "[--from=<server>]" | 9 | refresh_cache.help_arguments = "[--from=<server>]" |
13 | refresh_cache.help = [[ | 10 | refresh_cache.help = [[ |
diff --git a/src/luarocks/admin_remove.lua b/src/luarocks/admin/cmd/remove.lua index 621f1317..763a166f 100644 --- a/src/luarocks/admin_remove.lua +++ b/src/luarocks/admin/cmd/remove.lua | |||
@@ -2,17 +2,15 @@ | |||
2 | --- Module implementing the luarocks-admin "remove" command. | 2 | --- Module implementing the luarocks-admin "remove" command. |
3 | -- Removes a rock or rockspec from a rocks server. | 3 | -- Removes a rock or rockspec from a rocks server. |
4 | local admin_remove = {} | 4 | local admin_remove = {} |
5 | package.loaded["luarocks.admin_remove"] = admin_remove | ||
6 | 5 | ||
7 | local cfg = require("luarocks.cfg") | 6 | local cfg = require("luarocks.core.cfg") |
8 | local util = require("luarocks.util") | 7 | local util = require("luarocks.util") |
9 | local dir = require("luarocks.dir") | 8 | local dir = require("luarocks.dir") |
10 | local manif = require("luarocks.manif") | 9 | local writer = require("luarocks.manif.writer") |
11 | local index = require("luarocks.index") | 10 | local index = require("luarocks.index") |
12 | local fs = require("luarocks.fs") | 11 | local fs = require("luarocks.fs") |
13 | local cache = require("luarocks.cache") | 12 | local cache = require("luarocks.admin.cache") |
14 | 13 | ||
15 | util.add_run_function(admin_remove) | ||
16 | admin_remove.help_summary = "Remove a rock or rockspec from a rocks server." | 14 | admin_remove.help_summary = "Remove a rock or rockspec from a rocks server." |
17 | admin_remove.help_arguments = "[--server=<server>] [--no-refresh] {<rockspec>|<rock>...}" | 15 | admin_remove.help_arguments = "[--server=<server>] [--no-refresh] {<rockspec>|<rock>...}" |
18 | admin_remove.help = [[ | 16 | admin_remove.help = [[ |
@@ -65,7 +63,7 @@ local function remove_files_from_server(refresh, rockfiles, server, upload_serve | |||
65 | if not ok then return nil, err end | 63 | if not ok then return nil, err end |
66 | 64 | ||
67 | util.printout("Updating manifest...") | 65 | util.printout("Updating manifest...") |
68 | manif.make_manifest(local_cache, "one", true) | 66 | writer.make_manifest(local_cache, "one", true) |
69 | util.printout("Updating index.html...") | 67 | util.printout("Updating index.html...") |
70 | index.make_index(local_cache) | 68 | index.make_index(local_cache) |
71 | 69 | ||
diff --git a/src/luarocks/build.lua b/src/luarocks/build.lua index 96b232ff..ceaa20dd 100644 --- a/src/luarocks/build.lua +++ b/src/luarocks/build.lua | |||
@@ -1,45 +1,15 @@ | |||
1 | 1 | ||
2 | --- Module implementing the LuaRocks "build" command. | ||
3 | -- Builds a rock, compiling its C parts if any. | ||
4 | local build = {} | 2 | local build = {} |
5 | package.loaded["luarocks.build"] = build | ||
6 | 3 | ||
7 | local pack = require("luarocks.pack") | ||
8 | local path = require("luarocks.path") | 4 | local path = require("luarocks.path") |
9 | local util = require("luarocks.util") | 5 | local util = require("luarocks.util") |
10 | local repos = require("luarocks.repos") | ||
11 | local fetch = require("luarocks.fetch") | 6 | local fetch = require("luarocks.fetch") |
12 | local fs = require("luarocks.fs") | 7 | local fs = require("luarocks.fs") |
13 | local dir = require("luarocks.dir") | 8 | local dir = require("luarocks.dir") |
14 | local deps = require("luarocks.deps") | 9 | local deps = require("luarocks.deps") |
15 | local manif = require("luarocks.manif") | 10 | local cfg = require("luarocks.core.cfg") |
16 | local remove = require("luarocks.remove") | 11 | local repos = require("luarocks.repos") |
17 | local cfg = require("luarocks.cfg") | 12 | local writer = require("luarocks.manif.writer") |
18 | |||
19 | util.add_run_function(build) | ||
20 | build.help_summary = "Build/compile a rock." | ||
21 | build.help_arguments = "[--pack-binary-rock] [--keep] {<rockspec>|<rock>|<name> [<version>]}" | ||
22 | build.help = [[ | ||
23 | Build and install a rock, compiling its C parts if any. | ||
24 | Argument may be a rockspec file, a source rock file | ||
25 | or the name of a rock to be fetched from a repository. | ||
26 | |||
27 | --pack-binary-rock Do not install rock. Instead, produce a .rock file | ||
28 | with the contents of compilation in the current | ||
29 | directory. | ||
30 | |||
31 | --keep Do not remove previously installed versions of the | ||
32 | rock after building a new one. This behavior can | ||
33 | be made permanent by setting keep_other_versions=true | ||
34 | in the configuration file. | ||
35 | |||
36 | --branch=<name> Override the `source.branch` field in the loaded | ||
37 | rockspec. Allows to specify a different branch to | ||
38 | fetch. Particularly for SCM rocks. | ||
39 | |||
40 | --only-deps Installs only the dependencies of the rock. | ||
41 | |||
42 | ]]..util.deps_mode_help() | ||
43 | 13 | ||
44 | --- Install files to a given location. | 14 | --- Install files to a given location. |
45 | -- Takes a table where the array part is a list of filenames to be copied. | 15 | -- Takes a table where the array part is a list of filenames to be copied. |
@@ -148,6 +118,31 @@ local function install_default_docs(name, version) | |||
148 | end | 118 | end |
149 | end | 119 | end |
150 | 120 | ||
121 | local function check_macosx_deployment_target(rockspec) | ||
122 | local target = rockspec.build.macosx_deployment_target | ||
123 | local function minor(version) | ||
124 | return tonumber(version and version:match("^[^.]+%.([^.]+)")) | ||
125 | end | ||
126 | local function patch_variable(var, target) | ||
127 | if rockspec.variables[var]:match("MACOSX_DEPLOYMENT_TARGET") then | ||
128 | rockspec.variables[var] = (rockspec.variables[var]):gsub("MACOSX_DEPLOYMENT_TARGET=[^ ]*", "MACOSX_DEPLOYMENT_TARGET="..target) | ||
129 | else | ||
130 | rockspec.variables[var] = "env MACOSX_DEPLOYMENT_TARGET="..target.." "..rockspec.variables[var] | ||
131 | end | ||
132 | end | ||
133 | if cfg.platforms.macosx and rockspec:format_is_at_least("3.0") and target then | ||
134 | local version = util.popen_read("sw_vers -productVersion") | ||
135 | local versionminor = minor(version) | ||
136 | local targetminor = minor(target) | ||
137 | if targetminor > versionminor then | ||
138 | return nil, ("This rock requires Mac OSX 10.%d, and you are running 10.%d."):format(targetminor, versionminor) | ||
139 | end | ||
140 | patch_variable("CC", target) | ||
141 | patch_variable("LD", target) | ||
142 | end | ||
143 | return true | ||
144 | end | ||
145 | |||
151 | --- Build and install a rock given a rockspec. | 146 | --- Build and install a rock given a rockspec. |
152 | -- @param rockspec_file string: local or remote filename of a rockspec. | 147 | -- @param rockspec_file string: local or remote filename of a rockspec. |
153 | -- @param need_to_fetch boolean: true if sources need to be fetched, | 148 | -- @param need_to_fetch boolean: true if sources need to be fetched, |
@@ -245,6 +240,11 @@ function build.build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_m | |||
245 | end | 240 | end |
246 | end | 241 | end |
247 | 242 | ||
243 | ok, err = check_macosx_deployment_target(rockspec) | ||
244 | if not ok then | ||
245 | return nil, err | ||
246 | end | ||
247 | |||
248 | if build_spec.type ~= "none" then | 248 | if build_spec.type ~= "none" then |
249 | 249 | ||
250 | -- Temporary compatibility | 250 | -- Temporary compatibility |
@@ -314,7 +314,7 @@ function build.build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_m | |||
314 | fs.pop_dir() | 314 | fs.pop_dir() |
315 | end | 315 | end |
316 | 316 | ||
317 | ok, err = manif.make_rock_manifest(name, version) | 317 | ok, err = writer.make_rock_manifest(name, version) |
318 | if err then return nil, err end | 318 | if err then return nil, err end |
319 | 319 | ||
320 | ok, err = repos.deploy_files(name, version, repos.should_wrap_bin_scripts(rockspec), deps_mode) | 320 | ok, err = repos.deploy_files(name, version, repos.should_wrap_bin_scripts(rockspec), deps_mode) |
@@ -333,83 +333,4 @@ function build.build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_m | |||
333 | return name, version | 333 | return name, version |
334 | end | 334 | end |
335 | 335 | ||
336 | --- Build and install a rock. | ||
337 | -- @param rock_file string: local or remote filename of a rock. | ||
338 | -- @param need_to_fetch boolean: true if sources need to be fetched, | ||
339 | -- false if the rockspec was obtained from inside a source rock. | ||
340 | -- @param deps_mode: string: Which trees to check dependencies for: | ||
341 | -- "one" for the current default tree, "all" for all trees, | ||
342 | -- "order" for all trees with priority >= the current default, "none" for no trees. | ||
343 | -- @param build_only_deps boolean: true to build the listed dependencies only. | ||
344 | -- @return boolean or (nil, string, [string]): True if build was successful, | ||
345 | -- or false and an error message and an optional error code. | ||
346 | function build.build_rock(rock_file, need_to_fetch, deps_mode, build_only_deps) | ||
347 | assert(type(rock_file) == "string") | ||
348 | assert(type(need_to_fetch) == "boolean") | ||
349 | |||
350 | local ok, err, errcode | ||
351 | local unpack_dir | ||
352 | unpack_dir, err, errcode = fetch.fetch_and_unpack_rock(rock_file) | ||
353 | if not unpack_dir then | ||
354 | return nil, err, errcode | ||
355 | end | ||
356 | local rockspec_file = path.rockspec_name_from_rock(rock_file) | ||
357 | ok, err = fs.change_dir(unpack_dir) | ||
358 | if not ok then return nil, err end | ||
359 | ok, err, errcode = build.build_rockspec(rockspec_file, need_to_fetch, false, deps_mode, build_only_deps) | ||
360 | fs.pop_dir() | ||
361 | return ok, err, errcode | ||
362 | end | ||
363 | |||
364 | local function do_build(name, version, deps_mode, build_only_deps) | ||
365 | if name:match("%.rockspec$") then | ||
366 | return build.build_rockspec(name, true, false, deps_mode, build_only_deps) | ||
367 | elseif name:match("%.src%.rock$") then | ||
368 | return build.build_rock(name, false, deps_mode, build_only_deps) | ||
369 | elseif name:match("%.all%.rock$") then | ||
370 | local install = require("luarocks.install") | ||
371 | local install_fun = build_only_deps and install.install_binary_rock_deps or install.install_binary_rock | ||
372 | return install_fun(name, deps_mode) | ||
373 | elseif name:match("%.rock$") then | ||
374 | return build.build_rock(name, true, deps_mode, build_only_deps) | ||
375 | elseif not name:match(dir.separator) then | ||
376 | local search = require("luarocks.search") | ||
377 | return search.act_on_src_or_rockspec(do_build, name:lower(), version, nil, deps_mode, build_only_deps) | ||
378 | end | ||
379 | return nil, "Don't know what to do with "..name | ||
380 | end | ||
381 | |||
382 | --- Driver function for "build" command. | ||
383 | -- @param name string: A local or remote rockspec or rock file. | ||
384 | -- If a package name is given, forwards the request to "search" and, | ||
385 | -- if returned a result, installs the matching rock. | ||
386 | -- @param version string: When passing a package name, a version number may | ||
387 | -- also be given. | ||
388 | -- @return boolean or (nil, string, exitcode): True if build was successful; nil and an | ||
389 | -- error message otherwise. exitcode is optionally returned. | ||
390 | function build.command(flags, name, version) | ||
391 | if type(name) ~= "string" then | ||
392 | return nil, "Argument missing. "..util.see_help("build") | ||
393 | end | ||
394 | assert(type(version) == "string" or not version) | ||
395 | |||
396 | if flags["pack-binary-rock"] then | ||
397 | return pack.pack_binary_rock(name, version, do_build, name, version, deps.get_deps_mode(flags)) | ||
398 | else | ||
399 | local ok, err = fs.check_command_permissions(flags) | ||
400 | if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end | ||
401 | ok, err = do_build(name, version, deps.get_deps_mode(flags), flags["only-deps"]) | ||
402 | if not ok then return nil, err end | ||
403 | name, version = ok, err | ||
404 | |||
405 | if (not flags["only-deps"]) and (not flags["keep"]) and not cfg.keep_other_versions then | ||
406 | local ok, err = remove.remove_other_versions(name, version, flags["force"], flags["force-fast"]) | ||
407 | if not ok then util.printerr(err) end | ||
408 | end | ||
409 | |||
410 | manif.check_dependencies(nil, deps.get_deps_mode(flags)) | ||
411 | return name, version | ||
412 | end | ||
413 | end | ||
414 | |||
415 | return build | 336 | return build |
diff --git a/src/luarocks/build/builtin.lua b/src/luarocks/build/builtin.lua index ccefaa3b..403a8aaf 100644 --- a/src/luarocks/build/builtin.lua +++ b/src/luarocks/build/builtin.lua | |||
@@ -7,7 +7,7 @@ local unpack = unpack or table.unpack | |||
7 | local fs = require("luarocks.fs") | 7 | local fs = require("luarocks.fs") |
8 | local path = require("luarocks.path") | 8 | local path = require("luarocks.path") |
9 | local util = require("luarocks.util") | 9 | local util = require("luarocks.util") |
10 | local cfg = require("luarocks.cfg") | 10 | local cfg = require("luarocks.core.cfg") |
11 | local dir = require("luarocks.dir") | 11 | local dir = require("luarocks.dir") |
12 | 12 | ||
13 | --- Run a command displaying its execution on standard output. | 13 | --- Run a command displaying its execution on standard output. |
@@ -49,7 +49,7 @@ end | |||
49 | -- nil and an error message otherwise. | 49 | -- nil and an error message otherwise. |
50 | function builtin.run(rockspec) | 50 | function builtin.run(rockspec) |
51 | assert(type(rockspec) == "table") | 51 | assert(type(rockspec) == "table") |
52 | local compile_object, compile_library, compile_wrapper_binary --TODO EXEWRAPPER | 52 | local compile_object, compile_library, compile_static_library, compile_wrapper_binary --TODO EXEWRAPPER |
53 | 53 | ||
54 | local build = rockspec.build | 54 | local build = rockspec.build |
55 | local variables = rockspec.variables | 55 | local variables = rockspec.variables |
@@ -83,6 +83,15 @@ function builtin.run(rockspec) | |||
83 | local ok = execute(variables.LD.." "..variables.LIBFLAG, "-o", library, unpack(extras)) | 83 | local ok = execute(variables.LD.." "..variables.LIBFLAG, "-o", library, unpack(extras)) |
84 | return ok | 84 | return ok |
85 | end | 85 | end |
86 | --[[ TODO disable static libs until we fix the conflict in the manifest, which will take extending the manifest format. | ||
87 | compile_static_library = function(library, objects, libraries, libdirs, name) | ||
88 | local ok = execute(variables.AR, "rc", library, unpack(objects)) | ||
89 | if ok then | ||
90 | ok = execute(variables.RANLIB, library) | ||
91 | end | ||
92 | return ok | ||
93 | end | ||
94 | ]] | ||
86 | compile_wrapper_binary = function(fullname, name) | 95 | compile_wrapper_binary = function(fullname, name) |
87 | --TODO EXEWRAPPER | 96 | --TODO EXEWRAPPER |
88 | local fullbasename = fullname:gsub("%.lua$", ""):gsub("/", "\\") | 97 | local fullbasename = fullname:gsub("%.lua$", ""):gsub("/", "\\") |
@@ -129,6 +138,12 @@ function builtin.run(rockspec) | |||
129 | end | 138 | end |
130 | return ok | 139 | return ok |
131 | end | 140 | end |
141 | --[[ TODO disable static libs until we fix the conflict in the manifest, which will take extending the manifest format. | ||
142 | compile_static_library = function(library, objects, libraries, libdirs, name) | ||
143 | local ok = execute(variables.AR, "-out:"..library, unpack(objects)) | ||
144 | return ok | ||
145 | end | ||
146 | ]] | ||
132 | compile_wrapper_binary = function(fullname, name) | 147 | compile_wrapper_binary = function(fullname, name) |
133 | --TODO EXEWRAPPER | 148 | --TODO EXEWRAPPER |
134 | local fullbasename = fullname:gsub("%.lua$", ""):gsub("/", "\\") | 149 | local fullbasename = fullname:gsub("%.lua$", ""):gsub("/", "\\") |
@@ -170,6 +185,13 @@ function builtin.run(rockspec) | |||
170 | end | 185 | end |
171 | return execute(variables.LD.." "..variables.LIBFLAG, "-o", library, "-L"..variables.LUA_LIBDIR, unpack(extras)) | 186 | return execute(variables.LD.." "..variables.LIBFLAG, "-o", library, "-L"..variables.LUA_LIBDIR, unpack(extras)) |
172 | end | 187 | end |
188 | compile_static_library = function(library, objects, libraries, libdirs, name) | ||
189 | local ok = execute(variables.AR, "rc", library, unpack(objects)) | ||
190 | if ok then | ||
191 | ok = execute(variables.RANLIB, library) | ||
192 | end | ||
193 | return ok | ||
194 | end | ||
173 | compile_wrapper_binary = function(_, name) return true, name end | 195 | compile_wrapper_binary = function(_, name) return true, name end |
174 | --TODO EXEWRAPPER | 196 | --TODO EXEWRAPPER |
175 | end | 197 | end |
@@ -253,6 +275,17 @@ function builtin.run(rockspec) | |||
253 | if not ok then | 275 | if not ok then |
254 | return nil, "Failed compiling module "..module_name | 276 | return nil, "Failed compiling module "..module_name |
255 | end | 277 | end |
278 | --[[ TODO disable static libs until we fix the conflict in the manifest, which will take extending the manifest format. | ||
279 | module_name = name:match("([^.]*)$").."."..util.matchquote(cfg.static_lib_extension) | ||
280 | if moddir ~= "" then | ||
281 | module_name = dir.path(moddir, module_name) | ||
282 | end | ||
283 | lib_modules[module_name] = dir.path(libdir, module_name) | ||
284 | ok = compile_static_library(module_name, objects, info.libraries, info.libdirs, name) | ||
285 | if not ok then | ||
286 | return nil, "Failed compiling static library "..module_name | ||
287 | end | ||
288 | ]] | ||
256 | end | 289 | end |
257 | end | 290 | end |
258 | for _, mods in ipairs({{ tbl = lua_modules, perms = cfg.perm_read }, { tbl = lib_modules, perms = cfg.perm_exec }}) do | 291 | for _, mods in ipairs({{ tbl = lua_modules, perms = cfg.perm_read }, { tbl = lib_modules, perms = cfg.perm_exec }}) do |
diff --git a/src/luarocks/build/cmake.lua b/src/luarocks/build/cmake.lua index da5a31f1..8ee6b6b2 100644 --- a/src/luarocks/build/cmake.lua +++ b/src/luarocks/build/cmake.lua | |||
@@ -4,7 +4,7 @@ local cmake = {} | |||
4 | 4 | ||
5 | local fs = require("luarocks.fs") | 5 | local fs = require("luarocks.fs") |
6 | local util = require("luarocks.util") | 6 | local util = require("luarocks.util") |
7 | local cfg = require("luarocks.cfg") | 7 | local cfg = require("luarocks.core.cfg") |
8 | 8 | ||
9 | --- Driver function for the "cmake" build back-end. | 9 | --- Driver function for the "cmake" build back-end. |
10 | -- @param rockspec table: the loaded rockspec. | 10 | -- @param rockspec table: the loaded rockspec. |
@@ -52,13 +52,26 @@ function cmake.run(rockspec) | |||
52 | return nil, "Failed cmake." | 52 | return nil, "Failed cmake." |
53 | end | 53 | end |
54 | 54 | ||
55 | if not fs.execute_string(rockspec.variables.CMAKE.." --build build.luarocks --config Release") then | 55 | local do_build, do_install |
56 | return nil, "Failed building." | 56 | if rockspec:format_is_at_least("3.0") then |
57 | do_build = (build.build_pass == nil) and true or build.build_pass | ||
58 | do_install = (build.install_pass == nil) and true or build.install_pass | ||
59 | else | ||
60 | do_build = true | ||
61 | do_install = true | ||
57 | end | 62 | end |
58 | 63 | ||
59 | if not fs.execute_string(rockspec.variables.CMAKE.." --build build.luarocks --target install --config Release") then | 64 | if do_build then |
60 | return nil, "Failed installing." | 65 | if not fs.execute_string(rockspec.variables.CMAKE.." --build build.luarocks --config Release") then |
66 | return nil, "Failed building." | ||
67 | end | ||
61 | end | 68 | end |
69 | if do_install then | ||
70 | if not fs.execute_string(rockspec.variables.CMAKE.." --build build.luarocks --target install --config Release") then | ||
71 | return nil, "Failed installing." | ||
72 | end | ||
73 | end | ||
74 | |||
62 | return true | 75 | return true |
63 | end | 76 | end |
64 | 77 | ||
diff --git a/src/luarocks/build/make.lua b/src/luarocks/build/make.lua index 69e73c2e..ded015b7 100644 --- a/src/luarocks/build/make.lua +++ b/src/luarocks/build/make.lua | |||
@@ -6,7 +6,7 @@ local unpack = unpack or table.unpack | |||
6 | 6 | ||
7 | local fs = require("luarocks.fs") | 7 | local fs = require("luarocks.fs") |
8 | local util = require("luarocks.util") | 8 | local util = require("luarocks.util") |
9 | local cfg = require("luarocks.cfg") | 9 | local cfg = require("luarocks.core.cfg") |
10 | 10 | ||
11 | --- Call "make" with given target and variables | 11 | --- Call "make" with given target and variables |
12 | -- @param make_cmd string: the make command to be used (typically | 12 | -- @param make_cmd string: the make command to be used (typically |
diff --git a/src/luarocks/cmd/build.lua b/src/luarocks/cmd/build.lua new file mode 100644 index 00000000..a6b67b92 --- /dev/null +++ b/src/luarocks/cmd/build.lua | |||
@@ -0,0 +1,119 @@ | |||
1 | |||
2 | --- Module implementing the LuaRocks "build" command. | ||
3 | -- Builds a rock, compiling its C parts if any. | ||
4 | local cmd_build = {} | ||
5 | |||
6 | local pack = require("luarocks.pack") | ||
7 | local path = require("luarocks.path") | ||
8 | local util = require("luarocks.util") | ||
9 | local fetch = require("luarocks.fetch") | ||
10 | local fs = require("luarocks.fs") | ||
11 | local dir = require("luarocks.dir") | ||
12 | local deps = require("luarocks.deps") | ||
13 | local remove = require("luarocks.remove") | ||
14 | local cfg = require("luarocks.core.cfg") | ||
15 | local build = require("luarocks.build") | ||
16 | local writer = require("luarocks.manif.writer") | ||
17 | |||
18 | cmd_build.help_summary = "build/compile a rock." | ||
19 | cmd_build.help_arguments = "[--pack-binary-rock] [--keep] {<rockspec>|<rock>|<name> [<version>]}" | ||
20 | cmd_build.help = [[ | ||
21 | Build and install a rock, compiling its C parts if any. | ||
22 | Argument may be a rockspec file, a source rock file | ||
23 | or the name of a rock to be fetched from a repository. | ||
24 | |||
25 | --pack-binary-rock Do not install rock. Instead, produce a .rock file | ||
26 | with the contents of compilation in the current | ||
27 | directory. | ||
28 | |||
29 | --keep Do not remove previously installed versions of the | ||
30 | rock after building a new one. This behavior can | ||
31 | be made permanent by setting keep_other_versions=true | ||
32 | in the configuration file. | ||
33 | |||
34 | --branch=<name> Override the `source.branch` field in the loaded | ||
35 | rockspec. Allows to specify a different branch to | ||
36 | fetch. Particularly for SCM rocks. | ||
37 | |||
38 | --only-deps Installs only the dependencies of the rock. | ||
39 | |||
40 | ]]..util.deps_mode_help() | ||
41 | |||
42 | --- Build and install a rock. | ||
43 | -- @param rock_file string: local or remote filename of a rock. | ||
44 | -- @param need_to_fetch boolean: true if sources need to be fetched, | ||
45 | -- false if the rockspec was obtained from inside a source rock. | ||
46 | -- @param deps_mode: string: Which trees to check dependencies for: | ||
47 | -- "one" for the current default tree, "all" for all trees, | ||
48 | -- "order" for all trees with priority >= the current default, "none" for no trees. | ||
49 | -- @param build_only_deps boolean: true to build the listed dependencies only. | ||
50 | -- @return boolean or (nil, string, [string]): True if build was successful, | ||
51 | -- or false and an error message and an optional error code. | ||
52 | local function build_rock(rock_file, need_to_fetch, deps_mode, build_only_deps) | ||
53 | assert(type(rock_file) == "string") | ||
54 | assert(type(need_to_fetch) == "boolean") | ||
55 | |||
56 | local ok, err, errcode | ||
57 | local unpack_dir | ||
58 | unpack_dir, err, errcode = fetch.fetch_and_unpack_rock(rock_file) | ||
59 | if not unpack_dir then | ||
60 | return nil, err, errcode | ||
61 | end | ||
62 | local rockspec_file = path.rockspec_name_from_rock(rock_file) | ||
63 | ok, err = fs.change_dir(unpack_dir) | ||
64 | if not ok then return nil, err end | ||
65 | ok, err, errcode = build.build_rockspec(rockspec_file, need_to_fetch, false, deps_mode, build_only_deps) | ||
66 | fs.pop_dir() | ||
67 | return ok, err, errcode | ||
68 | end | ||
69 | |||
70 | local function do_build(name, version, deps_mode, build_only_deps) | ||
71 | if name:match("%.rockspec$") then | ||
72 | return build.build_rockspec(name, true, false, deps_mode, build_only_deps) | ||
73 | elseif name:match("%.src%.rock$") then | ||
74 | return build_rock(name, false, deps_mode, build_only_deps) | ||
75 | elseif name:match("%.all%.rock$") then | ||
76 | return build_rock(name, true, deps_mode, build_only_deps) | ||
77 | elseif name:match("%.rock$") then | ||
78 | return build_rock(name, true, deps_mode, build_only_deps) | ||
79 | elseif not name:match(dir.separator) then | ||
80 | local search = require("luarocks.search") | ||
81 | return search.act_on_src_or_rockspec(do_build, name:lower(), version, nil, deps_mode, build_only_deps) | ||
82 | end | ||
83 | return nil, "Don't know what to do with "..name | ||
84 | end | ||
85 | |||
86 | --- Driver function for "build" command. | ||
87 | -- @param name string: A local or remote rockspec or rock file. | ||
88 | -- If a package name is given, forwards the request to "search" and, | ||
89 | -- if returned a result, installs the matching rock. | ||
90 | -- @param version string: When passing a package name, a version number may | ||
91 | -- also be given. | ||
92 | -- @return boolean or (nil, string, exitcode): True if build was successful; nil and an | ||
93 | -- error message otherwise. exitcode is optionally returned. | ||
94 | function cmd_build.command(flags, name, version) | ||
95 | if type(name) ~= "string" then | ||
96 | return nil, "Argument missing. "..util.see_help("build") | ||
97 | end | ||
98 | assert(type(version) == "string" or not version) | ||
99 | |||
100 | if flags["pack-binary-rock"] then | ||
101 | return pack.pack_binary_rock(name, version, do_build, name, version, deps.get_deps_mode(flags)) | ||
102 | else | ||
103 | local ok, err = fs.check_command_permissions(flags) | ||
104 | if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end | ||
105 | ok, err = do_build(name, version, deps.get_deps_mode(flags), flags["only-deps"]) | ||
106 | if not ok then return nil, err end | ||
107 | name, version = ok, err | ||
108 | |||
109 | if (not flags["only-deps"]) and (not flags["keep"]) and not cfg.keep_other_versions then | ||
110 | local ok, err = remove.remove_other_versions(name, version, flags["force"], flags["force-fast"]) | ||
111 | if not ok then util.printerr(err) end | ||
112 | end | ||
113 | |||
114 | writer.check_dependencies(nil, deps.get_deps_mode(flags)) | ||
115 | return name, version | ||
116 | end | ||
117 | end | ||
118 | |||
119 | return cmd_build | ||
diff --git a/src/luarocks/config_cmd.lua b/src/luarocks/cmd/config.lua index fe3cc637..b68f7898 100644 --- a/src/luarocks/config_cmd.lua +++ b/src/luarocks/cmd/config.lua | |||
@@ -2,11 +2,10 @@ | |||
2 | -- Queries information about the LuaRocks configuration. | 2 | -- Queries information about the LuaRocks configuration. |
3 | local config_cmd = {} | 3 | local config_cmd = {} |
4 | 4 | ||
5 | local cfg = require("luarocks.cfg") | 5 | local cfg = require("luarocks.core.cfg") |
6 | local util = require("luarocks.util") | 6 | local util = require("luarocks.util") |
7 | local dir = require("luarocks.dir") | 7 | local dir = require("luarocks.dir") |
8 | 8 | ||
9 | util.add_run_function(config_cmd) | ||
10 | config_cmd.help_summary = "Query information about the LuaRocks configuration." | 9 | config_cmd.help_summary = "Query information about the LuaRocks configuration." |
11 | config_cmd.help_arguments = "<flag>" | 10 | config_cmd.help_arguments = "<flag>" |
12 | config_cmd.help = [[ | 11 | config_cmd.help = [[ |
diff --git a/src/luarocks/doc.lua b/src/luarocks/cmd/doc.lua index 423ebe02..5d521276 100644 --- a/src/luarocks/doc.lua +++ b/src/luarocks/cmd/doc.lua | |||
@@ -2,7 +2,6 @@ | |||
2 | --- Module implementing the LuaRocks "doc" command. | 2 | --- Module implementing the LuaRocks "doc" command. |
3 | -- Shows documentation for an installed rock. | 3 | -- Shows documentation for an installed rock. |
4 | local doc = {} | 4 | local doc = {} |
5 | package.loaded["luarocks.doc"] = doc | ||
6 | 5 | ||
7 | local util = require("luarocks.util") | 6 | local util = require("luarocks.util") |
8 | local search = require("luarocks.search") | 7 | local search = require("luarocks.search") |
@@ -12,7 +11,6 @@ local fetch = require("luarocks.fetch") | |||
12 | local fs = require("luarocks.fs") | 11 | local fs = require("luarocks.fs") |
13 | local download = require("luarocks.download") | 12 | local download = require("luarocks.download") |
14 | 13 | ||
15 | util.add_run_function(doc) | ||
16 | doc.help_summary = "Show documentation for an installed rock." | 14 | doc.help_summary = "Show documentation for an installed rock." |
17 | 15 | ||
18 | doc.help = [[ | 16 | doc.help = [[ |
diff --git a/src/luarocks/cmd/download.lua b/src/luarocks/cmd/download.lua new file mode 100644 index 00000000..9c119f6e --- /dev/null +++ b/src/luarocks/cmd/download.lua | |||
@@ -0,0 +1,45 @@ | |||
1 | |||
2 | --- Module implementing the luarocks "download" command. | ||
3 | -- Download a rock from the repository. | ||
4 | local cmd_download = {} | ||
5 | |||
6 | local util = require("luarocks.util") | ||
7 | local download = require("luarocks.download") | ||
8 | |||
9 | cmd_download.help_summary = "Download a specific rock file from a rocks server." | ||
10 | cmd_download.help_arguments = "[--all] [--arch=<arch> | --source | --rockspec] [<name> [<version>]]" | ||
11 | cmd_download.help = [[ | ||
12 | --all Download all files if there are multiple matches. | ||
13 | --source Download .src.rock if available. | ||
14 | --rockspec Download .rockspec if available. | ||
15 | --arch=<arch> Download rock for a specific architecture. | ||
16 | ]] | ||
17 | |||
18 | --- Driver function for the "download" command. | ||
19 | -- @param name string: a rock name. | ||
20 | -- @param version string or nil: if the name of a package is given, a | ||
21 | -- version may also be passed. | ||
22 | -- @return boolean or (nil, string): true if successful or nil followed | ||
23 | -- by an error message. | ||
24 | function cmd_download.command(flags, name, version) | ||
25 | assert(type(version) == "string" or not version) | ||
26 | if type(name) ~= "string" and not flags["all"] then | ||
27 | return nil, "Argument missing. "..util.see_help("download") | ||
28 | end | ||
29 | if not name then name, version = "", "" end | ||
30 | |||
31 | local arch | ||
32 | |||
33 | if flags["source"] then | ||
34 | arch = "src" | ||
35 | elseif flags["rockspec"] then | ||
36 | arch = "rockspec" | ||
37 | elseif flags["arch"] then | ||
38 | arch = flags["arch"] | ||
39 | end | ||
40 | |||
41 | local dl, err = download.download(arch, name:lower(), version, flags["all"]) | ||
42 | return dl and true, err | ||
43 | end | ||
44 | |||
45 | return cmd_download | ||
diff --git a/src/luarocks/help.lua b/src/luarocks/cmd/help.lua index 10eb2287..b986534c 100644 --- a/src/luarocks/help.lua +++ b/src/luarocks/cmd/help.lua | |||
@@ -7,12 +7,11 @@ | |||
7 | local help = {} | 7 | local help = {} |
8 | 8 | ||
9 | local util = require("luarocks.util") | 9 | local util = require("luarocks.util") |
10 | local cfg = require("luarocks.cfg") | 10 | local cfg = require("luarocks.core.cfg") |
11 | local dir = require("luarocks.dir") | 11 | local dir = require("luarocks.dir") |
12 | 12 | ||
13 | local program = util.this_program("luarocks") | 13 | local program = util.this_program("luarocks") |
14 | 14 | ||
15 | util.add_run_function(help) | ||
16 | help.help_summary = "Help on commands. Type '"..program.." help <command>' for more." | 15 | help.help_summary = "Help on commands. Type '"..program.." help <command>' for more." |
17 | 16 | ||
18 | help.help_arguments = "[<command>]" | 17 | help.help_arguments = "[<command>]" |
@@ -48,7 +47,7 @@ function help.command(flags, command) | |||
48 | print_section("NAME") | 47 | print_section("NAME") |
49 | util.printout("\t"..program..[[ - ]]..program_description) | 48 | util.printout("\t"..program..[[ - ]]..program_description) |
50 | print_section("SYNOPSIS") | 49 | print_section("SYNOPSIS") |
51 | util.printout("\t"..program..[[ [--server=<server> | --only-server=<server>] [--tree=<tree>] [VAR=VALUE]... <command> [<argument>] ]]) | 50 | util.printout("\t"..program..[[ [<flags...>] [VAR=VALUE]... <command> [<argument>] ]]) |
52 | print_section("GENERAL OPTIONS") | 51 | print_section("GENERAL OPTIONS") |
53 | util.printout([[ | 52 | util.printout([[ |
54 | These apply to all commands, as appropriate: | 53 | These apply to all commands, as appropriate: |
diff --git a/src/luarocks/install.lua b/src/luarocks/cmd/install.lua index e28c24f0..8b4a154b 100644 --- a/src/luarocks/install.lua +++ b/src/luarocks/cmd/install.lua | |||
@@ -1,7 +1,6 @@ | |||
1 | --- Module implementing the LuaRocks "install" command. | 1 | --- Module implementing the LuaRocks "install" command. |
2 | -- Installs binary rocks. | 2 | -- Installs binary rocks. |
3 | local install = {} | 3 | local install = {} |
4 | package.loaded["luarocks.install"] = install | ||
5 | 4 | ||
6 | local path = require("luarocks.path") | 5 | local path = require("luarocks.path") |
7 | local repos = require("luarocks.repos") | 6 | local repos = require("luarocks.repos") |
@@ -9,11 +8,11 @@ local fetch = require("luarocks.fetch") | |||
9 | local util = require("luarocks.util") | 8 | local util = require("luarocks.util") |
10 | local fs = require("luarocks.fs") | 9 | local fs = require("luarocks.fs") |
11 | local deps = require("luarocks.deps") | 10 | local deps = require("luarocks.deps") |
12 | local manif = require("luarocks.manif") | 11 | local writer = require("luarocks.manif.writer") |
13 | local remove = require("luarocks.remove") | 12 | local remove = require("luarocks.remove") |
14 | local cfg = require("luarocks.cfg") | 13 | local search = require("luarocks.search") |
14 | local cfg = require("luarocks.core.cfg") | ||
15 | 15 | ||
16 | util.add_run_function(install) | ||
17 | install.help_summary = "Install a rock." | 16 | install.help_summary = "Install a rock." |
18 | 17 | ||
19 | install.help_arguments = "{<rock>|<name> [<version>]}" | 18 | install.help_arguments = "{<rock>|<name> [<version>]}" |
@@ -75,7 +74,7 @@ function install.install_binary_rock(rock_file, deps_mode) | |||
75 | 74 | ||
76 | -- For compatibility with .rock files built with LuaRocks 1 | 75 | -- For compatibility with .rock files built with LuaRocks 1 |
77 | if not fs.exists(path.rock_manifest_file(name, version)) then | 76 | if not fs.exists(path.rock_manifest_file(name, version)) then |
78 | ok, err = manif.make_rock_manifest(name, version) | 77 | ok, err = writer.make_rock_manifest(name, version) |
79 | if err then return nil, err end | 78 | if err then return nil, err end |
80 | end | 79 | end |
81 | 80 | ||
@@ -156,7 +155,7 @@ function install.command(flags, name, version) | |||
156 | if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end | 155 | if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end |
157 | 156 | ||
158 | if name:match("%.rockspec$") or name:match("%.src%.rock$") then | 157 | if name:match("%.rockspec$") or name:match("%.src%.rock$") then |
159 | local build = require("luarocks.build") | 158 | local build = require("luarocks.cmd.build") |
160 | return build.command(flags, name) | 159 | return build.command(flags, name) |
161 | elseif name:match("%.rock$") then | 160 | elseif name:match("%.rock$") then |
162 | if flags["only-deps"] then | 161 | if flags["only-deps"] then |
@@ -172,10 +171,9 @@ function install.command(flags, name, version) | |||
172 | if not ok then util.printerr(err) end | 171 | if not ok then util.printerr(err) end |
173 | end | 172 | end |
174 | 173 | ||
175 | manif.check_dependencies(nil, deps.get_deps_mode(flags)) | 174 | writer.check_dependencies(nil, deps.get_deps_mode(flags)) |
176 | return name, version | 175 | return name, version |
177 | else | 176 | else |
178 | local search = require("luarocks.search") | ||
179 | local url, err = search.find_suitable_rock(search.make_query(name:lower(), version)) | 177 | local url, err = search.find_suitable_rock(search.make_query(name:lower(), version)) |
180 | if not url then | 178 | if not url then |
181 | return nil, err | 179 | return nil, err |
diff --git a/src/luarocks/lint.lua b/src/luarocks/cmd/lint.lua index 0fd81a20..c9ea45ea 100644 --- a/src/luarocks/lint.lua +++ b/src/luarocks/cmd/lint.lua | |||
@@ -2,13 +2,11 @@ | |||
2 | --- Module implementing the LuaRocks "lint" command. | 2 | --- Module implementing the LuaRocks "lint" command. |
3 | -- Utility function that checks syntax of the rockspec. | 3 | -- Utility function that checks syntax of the rockspec. |
4 | local lint = {} | 4 | local lint = {} |
5 | package.loaded["luarocks.lint"] = lint | ||
6 | 5 | ||
7 | local util = require("luarocks.util") | 6 | local util = require("luarocks.util") |
8 | local download = require("luarocks.download") | 7 | local download = require("luarocks.download") |
9 | local fetch = require("luarocks.fetch") | 8 | local fetch = require("luarocks.fetch") |
10 | 9 | ||
11 | util.add_run_function(lint) | ||
12 | lint.help_summary = "Check syntax of a rockspec." | 10 | lint.help_summary = "Check syntax of a rockspec." |
13 | lint.help_arguments = "<rockspec>" | 11 | lint.help_arguments = "<rockspec>" |
14 | lint.help = [[ | 12 | lint.help = [[ |
diff --git a/src/luarocks/list.lua b/src/luarocks/cmd/list.lua index c65e058f..9dff22ac 100644 --- a/src/luarocks/list.lua +++ b/src/luarocks/cmd/list.lua | |||
@@ -2,15 +2,13 @@ | |||
2 | --- Module implementing the LuaRocks "list" command. | 2 | --- Module implementing the LuaRocks "list" command. |
3 | -- Lists currently installed rocks. | 3 | -- Lists currently installed rocks. |
4 | local list = {} | 4 | local list = {} |
5 | package.loaded["luarocks.list"] = list | ||
6 | 5 | ||
7 | local search = require("luarocks.search") | 6 | local search = require("luarocks.search") |
8 | local deps = require("luarocks.deps") | 7 | local vers = require("luarocks.vers") |
9 | local cfg = require("luarocks.cfg") | 8 | local cfg = require("luarocks.core.cfg") |
10 | local util = require("luarocks.util") | 9 | local util = require("luarocks.util") |
11 | local path = require("luarocks.path") | 10 | local path = require("luarocks.path") |
12 | 11 | ||
13 | util.add_run_function(list) | ||
14 | list.help_summary = "List currently installed rocks." | 12 | list.help_summary = "List currently installed rocks." |
15 | list.help_arguments = "[--porcelain] <filter>" | 13 | list.help_arguments = "[--porcelain] <filter>" |
16 | list.help = [[ | 14 | list.help = [[ |
@@ -30,7 +28,7 @@ local function check_outdated(trees, query) | |||
30 | local outdated = {} | 28 | local outdated = {} |
31 | for name, versions in util.sortedpairs(results_installed) do | 29 | for name, versions in util.sortedpairs(results_installed) do |
32 | versions = util.keys(versions) | 30 | versions = util.keys(versions) |
33 | table.sort(versions, deps.compare_versions) | 31 | table.sort(versions, vers.compare_versions) |
34 | local latest_installed = versions[1] | 32 | local latest_installed = versions[1] |
35 | 33 | ||
36 | local query_available = search.make_query(name:lower()) | 34 | local query_available = search.make_query(name:lower()) |
@@ -39,11 +37,11 @@ local function check_outdated(trees, query) | |||
39 | 37 | ||
40 | if results_available[name] then | 38 | if results_available[name] then |
41 | local available_versions = util.keys(results_available[name]) | 39 | local available_versions = util.keys(results_available[name]) |
42 | table.sort(available_versions, deps.compare_versions) | 40 | table.sort(available_versions, vers.compare_versions) |
43 | local latest_available = available_versions[1] | 41 | local latest_available = available_versions[1] |
44 | local latest_available_repo = results_available[name][latest_available][1].repo | 42 | local latest_available_repo = results_available[name][latest_available][1].repo |
45 | 43 | ||
46 | if deps.compare_versions(latest_available, latest_installed) then | 44 | if vers.compare_versions(latest_available, latest_installed) then |
47 | table.insert(outdated, { name = name, installed = latest_installed, available = latest_available, repo = latest_available_repo }) | 45 | table.insert(outdated, { name = name, installed = latest_installed, available = latest_available, repo = latest_available_repo }) |
48 | end | 46 | end |
49 | end | 47 | end |
diff --git a/src/luarocks/make.lua b/src/luarocks/cmd/make.lua index e59dee37..bfdddb37 100644 --- a/src/luarocks/make.lua +++ b/src/luarocks/cmd/make.lua | |||
@@ -4,19 +4,17 @@ | |||
4 | -- it does not fetch sources, etc., assuming everything is | 4 | -- it does not fetch sources, etc., assuming everything is |
5 | -- available in the current directory. | 5 | -- available in the current directory. |
6 | local make = {} | 6 | local make = {} |
7 | package.loaded["luarocks.make"] = make | ||
8 | 7 | ||
9 | local build = require("luarocks.build") | 8 | local build = require("luarocks.build") |
10 | local fs = require("luarocks.fs") | 9 | local fs = require("luarocks.fs") |
11 | local util = require("luarocks.util") | 10 | local util = require("luarocks.util") |
12 | local cfg = require("luarocks.cfg") | 11 | local cfg = require("luarocks.core.cfg") |
13 | local fetch = require("luarocks.fetch") | 12 | local fetch = require("luarocks.fetch") |
14 | local pack = require("luarocks.pack") | 13 | local pack = require("luarocks.pack") |
15 | local remove = require("luarocks.remove") | 14 | local remove = require("luarocks.remove") |
16 | local deps = require("luarocks.deps") | 15 | local deps = require("luarocks.deps") |
17 | local manif = require("luarocks.manif") | 16 | local writer = require("luarocks.manif.writer") |
18 | 17 | ||
19 | util.add_run_function(make) | ||
20 | make.help_summary = "Compile package in current directory using a rockspec." | 18 | make.help_summary = "Compile package in current directory using a rockspec." |
21 | make.help_arguments = "[--pack-binary-rock] [<rockspec>]" | 19 | make.help_arguments = "[--pack-binary-rock] [<rockspec>]" |
22 | make.help = [[ | 20 | make.help = [[ |
@@ -87,7 +85,7 @@ function make.command(flags, rockspec) | |||
87 | if not ok then util.printerr(err) end | 85 | if not ok then util.printerr(err) end |
88 | end | 86 | end |
89 | 87 | ||
90 | manif.check_dependencies(nil, deps.get_deps_mode(flags)) | 88 | writer.check_dependencies(nil, deps.get_deps_mode(flags)) |
91 | return name, version | 89 | return name, version |
92 | end | 90 | end |
93 | end | 91 | end |
diff --git a/src/luarocks/new_version.lua b/src/luarocks/cmd/new_version.lua index 91f7607c..b13dbb97 100644 --- a/src/luarocks/new_version.lua +++ b/src/luarocks/cmd/new_version.lua | |||
@@ -10,7 +10,6 @@ local persist = require("luarocks.persist") | |||
10 | local fs = require("luarocks.fs") | 10 | local fs = require("luarocks.fs") |
11 | local type_check = require("luarocks.type_check") | 11 | local type_check = require("luarocks.type_check") |
12 | 12 | ||
13 | util.add_run_function(new_version) | ||
14 | new_version.help_summary = "Auto-write a rockspec for a new version of a rock." | 13 | new_version.help_summary = "Auto-write a rockspec for a new version of a rock." |
15 | new_version.help_arguments = "[--tag=<tag>] [<package>|<rockspec>] [<new_version>] [<new_url>]" | 14 | new_version.help_arguments = "[--tag=<tag>] [<package>|<rockspec>] [<new_version>] [<new_url>]" |
16 | new_version.help = [[ | 15 | new_version.help = [[ |
diff --git a/src/luarocks/cmd/pack.lua b/src/luarocks/cmd/pack.lua new file mode 100644 index 00000000..e43e5b3f --- /dev/null +++ b/src/luarocks/cmd/pack.lua | |||
@@ -0,0 +1,45 @@ | |||
1 | |||
2 | --- Module implementing the LuaRocks "pack" command. | ||
3 | -- Creates a rock, packing sources or binaries. | ||
4 | local cmd_pack = {} | ||
5 | |||
6 | local util = require("luarocks.util") | ||
7 | local pack = require("luarocks.pack") | ||
8 | |||
9 | cmd_pack.help_summary = "Create a rock, packing sources or binaries." | ||
10 | cmd_pack.help_arguments = "{<rockspec>|<name> [<version>]}" | ||
11 | cmd_pack.help = [[ | ||
12 | Argument may be a rockspec file, for creating a source rock, | ||
13 | or the name of an installed package, for creating a binary rock. | ||
14 | In the latter case, the app version may be given as a second | ||
15 | argument. | ||
16 | ]] | ||
17 | |||
18 | --- Driver function for the "pack" command. | ||
19 | -- @param arg string: may be a rockspec file, for creating a source rock, | ||
20 | -- or the name of an installed package, for creating a binary rock. | ||
21 | -- @param version string or nil: if the name of a package is given, a | ||
22 | -- version may also be passed. | ||
23 | -- @return boolean or (nil, string): true if successful or nil followed | ||
24 | -- by an error message. | ||
25 | function cmd_pack.command(flags, arg, version) | ||
26 | assert(type(version) == "string" or not version) | ||
27 | if type(arg) ~= "string" then | ||
28 | return nil, "Argument missing. "..util.see_help("pack") | ||
29 | end | ||
30 | |||
31 | local file, err | ||
32 | if arg:match(".*%.rockspec") then | ||
33 | file, err = pack.pack_source_rock(arg) | ||
34 | else | ||
35 | file, err = pack.pack_installed_rock(arg:lower(), version, flags["tree"]) | ||
36 | end | ||
37 | if err then | ||
38 | return nil, err | ||
39 | else | ||
40 | util.printout("Packed: "..file) | ||
41 | return true | ||
42 | end | ||
43 | end | ||
44 | |||
45 | return cmd_pack | ||
diff --git a/src/luarocks/path_cmd.lua b/src/luarocks/cmd/path.lua index eba85d46..516a0c47 100644 --- a/src/luarocks/path_cmd.lua +++ b/src/luarocks/cmd/path.lua | |||
@@ -4,9 +4,8 @@ | |||
4 | local path_cmd = {} | 4 | local path_cmd = {} |
5 | 5 | ||
6 | local util = require("luarocks.util") | 6 | local util = require("luarocks.util") |
7 | local cfg = require("luarocks.cfg") | 7 | local cfg = require("luarocks.core.cfg") |
8 | 8 | ||
9 | util.add_run_function(path_cmd) | ||
10 | path_cmd.help_summary = "Return the currently configured package path." | 9 | path_cmd.help_summary = "Return the currently configured package path." |
11 | path_cmd.help_arguments = "" | 10 | path_cmd.help_arguments = "" |
12 | path_cmd.help = [[ | 11 | path_cmd.help = [[ |
diff --git a/src/luarocks/purge.lua b/src/luarocks/cmd/purge.lua index 17724e84..bbce9f8c 100644 --- a/src/luarocks/purge.lua +++ b/src/luarocks/cmd/purge.lua | |||
@@ -2,19 +2,17 @@ | |||
2 | --- Module implementing the LuaRocks "purge" command. | 2 | --- Module implementing the LuaRocks "purge" command. |
3 | -- Remove all rocks from a given tree. | 3 | -- Remove all rocks from a given tree. |
4 | local purge = {} | 4 | local purge = {} |
5 | package.loaded["luarocks.purge"] = purge | ||
6 | 5 | ||
7 | local util = require("luarocks.util") | 6 | local util = require("luarocks.util") |
8 | local fs = require("luarocks.fs") | 7 | local fs = require("luarocks.fs") |
9 | local path = require("luarocks.path") | 8 | local path = require("luarocks.path") |
10 | local search = require("luarocks.search") | 9 | local search = require("luarocks.search") |
11 | local deps = require("luarocks.deps") | 10 | local vers = require("luarocks.vers") |
12 | local repos = require("luarocks.repos") | 11 | local repos = require("luarocks.repos") |
13 | local manif = require("luarocks.manif") | 12 | local writer = require("luarocks.manif.writer") |
14 | local cfg = require("luarocks.cfg") | 13 | local cfg = require("luarocks.core.cfg") |
15 | local remove = require("luarocks.remove") | 14 | local remove = require("luarocks.remove") |
16 | 15 | ||
17 | util.add_run_function(purge) | ||
18 | purge.help_summary = "Remove all installed rocks from a tree." | 16 | purge.help_summary = "Remove all installed rocks from a tree." |
19 | purge.help_arguments = "--tree=<tree> [--old-versions]" | 17 | purge.help_arguments = "--tree=<tree> [--old-versions]" |
20 | purge.help = [[ | 18 | purge.help = [[ |
@@ -50,13 +48,13 @@ function purge.command(flags) | |||
50 | 48 | ||
51 | search.manifest_search(results, path.rocks_dir(tree), query) | 49 | search.manifest_search(results, path.rocks_dir(tree), query) |
52 | 50 | ||
53 | local sort = function(a,b) return deps.compare_versions(b,a) end | 51 | local sort = function(a,b) return vers.compare_versions(b,a) end |
54 | if flags["old-versions"] then | 52 | if flags["old-versions"] then |
55 | sort = deps.compare_versions | 53 | sort = vers.compare_versions |
56 | end | 54 | end |
57 | 55 | ||
58 | for package, versions in util.sortedpairs(results) do | 56 | for package, versions in util.sortedpairs(results) do |
59 | for version, repositories in util.sortedpairs(versions, sort) do | 57 | for version, _ in util.sortedpairs(versions, sort) do |
60 | if flags["old-versions"] then | 58 | if flags["old-versions"] then |
61 | util.printout("Keeping "..package.." "..version.."...") | 59 | util.printout("Keeping "..package.." "..version.."...") |
62 | local ok, err = remove.remove_other_versions(package, version, flags["force"], flags["force-fast"]) | 60 | local ok, err = remove.remove_other_versions(package, version, flags["force"], flags["force-fast"]) |
@@ -73,7 +71,7 @@ function purge.command(flags) | |||
73 | end | 71 | end |
74 | end | 72 | end |
75 | end | 73 | end |
76 | return manif.make_manifest(cfg.rocks_dir, "one") | 74 | return writer.make_manifest(cfg.rocks_dir, "one") |
77 | end | 75 | end |
78 | 76 | ||
79 | return purge | 77 | return purge |
diff --git a/src/luarocks/cmd/remove.lua b/src/luarocks/cmd/remove.lua new file mode 100644 index 00000000..b8148ba7 --- /dev/null +++ b/src/luarocks/cmd/remove.lua | |||
@@ -0,0 +1,67 @@ | |||
1 | |||
2 | --- Module implementing the LuaRocks "remove" command. | ||
3 | -- Uninstalls rocks. | ||
4 | local cmd_remove = {} | ||
5 | |||
6 | local remove = require("luarocks.remove") | ||
7 | local util = require("luarocks.util") | ||
8 | local cfg = require("luarocks.core.cfg") | ||
9 | local fs = require("luarocks.fs") | ||
10 | local search = require("luarocks.search") | ||
11 | local path = require("luarocks.path") | ||
12 | local deps = require("luarocks.deps") | ||
13 | local writer = require("luarocks.manif.writer") | ||
14 | |||
15 | cmd_remove.help_summary = "Uninstall a rock." | ||
16 | cmd_remove.help_arguments = "[--force|--force-fast] <name> [<version>]" | ||
17 | cmd_remove.help = [[ | ||
18 | Argument is the name of a rock to be uninstalled. | ||
19 | If a version is not given, try to remove all versions at once. | ||
20 | Will only perform the removal if it does not break dependencies. | ||
21 | To override this check and force the removal, use --force. | ||
22 | To perform a forced removal without reporting dependency issues, | ||
23 | use --force-fast. | ||
24 | |||
25 | ]]..util.deps_mode_help() | ||
26 | |||
27 | --- Driver function for the "remove" command. | ||
28 | -- @param name string: name of a rock. If a version is given, refer to | ||
29 | -- a specific version; otherwise, try to remove all versions. | ||
30 | -- @param version string: When passing a package name, a version number | ||
31 | -- may also be given. | ||
32 | -- @return boolean or (nil, string, exitcode): True if removal was | ||
33 | -- successful, nil and an error message otherwise. exitcode is optionally returned. | ||
34 | function cmd_remove.command(flags, name, version) | ||
35 | if type(name) ~= "string" then | ||
36 | return nil, "Argument missing. "..util.see_help("remove") | ||
37 | end | ||
38 | |||
39 | local deps_mode = flags["deps-mode"] or cfg.deps_mode | ||
40 | |||
41 | local ok, err = fs.check_command_permissions(flags) | ||
42 | if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end | ||
43 | |||
44 | local rock_type = name:match("%.(rock)$") or name:match("%.(rockspec)$") | ||
45 | local filename = name | ||
46 | if rock_type then | ||
47 | name, version = path.parse_name(filename) | ||
48 | if not name then return nil, "Invalid "..rock_type.." filename: "..filename end | ||
49 | end | ||
50 | |||
51 | local results = {} | ||
52 | name = name:lower() | ||
53 | search.manifest_search(results, cfg.rocks_dir, search.make_query(name, version)) | ||
54 | if not results[name] then | ||
55 | return nil, "Could not find rock '"..name..(version and " "..version or "").."' in "..path.rocks_tree_to_string(cfg.root_dir) | ||
56 | end | ||
57 | |||
58 | local ok, err = remove.remove_search_results(results, name, deps_mode, flags["force"], flags["force-fast"]) | ||
59 | if not ok then | ||
60 | return nil, err | ||
61 | end | ||
62 | |||
63 | writer.check_dependencies(nil, deps.get_deps_mode(flags)) | ||
64 | return true | ||
65 | end | ||
66 | |||
67 | return cmd_remove | ||
diff --git a/src/luarocks/cmd/search.lua b/src/luarocks/cmd/search.lua new file mode 100644 index 00000000..c4e4058d --- /dev/null +++ b/src/luarocks/cmd/search.lua | |||
@@ -0,0 +1,74 @@ | |||
1 | |||
2 | --- Module implementing the LuaRocks "search" command. | ||
3 | -- Queries LuaRocks servers. | ||
4 | local cmd_search = {} | ||
5 | |||
6 | local cfg = require("luarocks.core.cfg") | ||
7 | local util = require("luarocks.util") | ||
8 | local search = require("luarocks.search") | ||
9 | |||
10 | cmd_search.help_summary = "Query the LuaRocks servers." | ||
11 | cmd_search.help_arguments = "[--source] [--binary] { <name> [<version>] | --all }" | ||
12 | cmd_search.help = [[ | ||
13 | --source Return only rockspecs and source rocks, | ||
14 | to be used with the "build" command. | ||
15 | --binary Return only pure Lua and binary rocks (rocks that can be used | ||
16 | with the "install" command without requiring a C toolchain). | ||
17 | --all List all contents of the server that are suitable to | ||
18 | this platform, do not filter by name. | ||
19 | ]] | ||
20 | |||
21 | --- Splits a list of search results into two lists, one for "source" results | ||
22 | -- to be used with the "build" command, and one for "binary" results to be | ||
23 | -- used with the "install" command. | ||
24 | -- @param results table: A search results table. | ||
25 | -- @return (table, table): Two tables, one for source and one for binary | ||
26 | -- results. | ||
27 | local function split_source_and_binary_results(results) | ||
28 | local sources, binaries = {}, {} | ||
29 | for name, versions in pairs(results) do | ||
30 | for version, repositories in pairs(versions) do | ||
31 | for _, repo in ipairs(repositories) do | ||
32 | local where = sources | ||
33 | if repo.arch == "all" or repo.arch == cfg.arch then | ||
34 | where = binaries | ||
35 | end | ||
36 | search.store_result(where, name, version, repo.arch, repo.repo) | ||
37 | end | ||
38 | end | ||
39 | end | ||
40 | return sources, binaries | ||
41 | end | ||
42 | |||
43 | --- Driver function for "search" command. | ||
44 | -- @param name string: A substring of a rock name to search. | ||
45 | -- @param version string or nil: a version may also be passed. | ||
46 | -- @return boolean or (nil, string): True if build was successful; nil and an | ||
47 | -- error message otherwise. | ||
48 | function cmd_search.command(flags, name, version) | ||
49 | if flags["all"] then | ||
50 | name, version = "", nil | ||
51 | end | ||
52 | |||
53 | if type(name) ~= "string" and not flags["all"] then | ||
54 | return nil, "Enter name and version or use --all. "..util.see_help("search") | ||
55 | end | ||
56 | |||
57 | local query = search.make_query(name:lower(), version) | ||
58 | query.exact_name = false | ||
59 | local results, err = search.search_repos(query) | ||
60 | local porcelain = flags["porcelain"] | ||
61 | util.title("Search results:", porcelain, "=") | ||
62 | local sources, binaries = split_source_and_binary_results(results) | ||
63 | if next(sources) and not flags["binary"] then | ||
64 | util.title("Rockspecs and source rocks:", porcelain) | ||
65 | search.print_results(sources, porcelain) | ||
66 | end | ||
67 | if next(binaries) and not flags["source"] then | ||
68 | util.title("Binary and pure-Lua rocks:", porcelain) | ||
69 | search.print_results(binaries, porcelain) | ||
70 | end | ||
71 | return true | ||
72 | end | ||
73 | |||
74 | return cmd_search | ||
diff --git a/src/luarocks/show.lua b/src/luarocks/cmd/show.lua index ac6273e0..16c8d34e 100644 --- a/src/luarocks/show.lua +++ b/src/luarocks/cmd/show.lua | |||
@@ -1,18 +1,16 @@ | |||
1 | --- Module implementing the LuaRocks "show" command. | 1 | --- Module implementing the LuaRocks "show" command. |
2 | -- Shows information about an installed rock. | 2 | -- Shows information about an installed rock. |
3 | local show = {} | 3 | local show = {} |
4 | package.loaded["luarocks.show"] = show | ||
5 | 4 | ||
6 | local search = require("luarocks.search") | 5 | local search = require("luarocks.search") |
7 | local cfg = require("luarocks.cfg") | 6 | local cfg = require("luarocks.core.cfg") |
8 | local util = require("luarocks.util") | 7 | local util = require("luarocks.util") |
9 | local path = require("luarocks.path") | 8 | local path = require("luarocks.path") |
10 | local deps = require("luarocks.deps") | 9 | local vers = require("luarocks.vers") |
11 | local fetch = require("luarocks.fetch") | 10 | local fetch = require("luarocks.fetch") |
12 | local manif = require("luarocks.manif") | 11 | local manif = require("luarocks.manif") |
13 | local repos = require("luarocks.repos") | 12 | local repos = require("luarocks.repos") |
14 | 13 | ||
15 | util.add_run_function(show) | ||
16 | show.help_summary = "Show information about an installed rock." | 14 | show.help_summary = "Show information about an installed rock." |
17 | 15 | ||
18 | show.help = [[ | 16 | show.help = [[ |
@@ -103,6 +101,8 @@ function show.command(flags, name, version) | |||
103 | if flags["rock-tree"] then util.printout(path.rocks_tree_to_string(repo)) | 101 | if flags["rock-tree"] then util.printout(path.rocks_tree_to_string(repo)) |
104 | elseif flags["rock-dir"] then util.printout(directory) | 102 | elseif flags["rock-dir"] then util.printout(directory) |
105 | elseif flags["home"] then util.printout(descript.homepage) | 103 | elseif flags["home"] then util.printout(descript.homepage) |
104 | elseif flags["issues"] then util.printout(descript.issues_url) | ||
105 | elseif flags["labels"] then util.printout(descript.labels and table.concat(descript.labels, "\n")) | ||
106 | elseif flags["modules"] then util.printout(keys_as_string(minfo.modules, "\n")) | 106 | elseif flags["modules"] then util.printout(keys_as_string(minfo.modules, "\n")) |
107 | elseif flags["deps"] then util.printout(keys_as_string(minfo.dependencies)) | 107 | elseif flags["deps"] then util.printout(keys_as_string(minfo.dependencies)) |
108 | elseif flags["rockspec"] then util.printout(rockspec_file) | 108 | elseif flags["rockspec"] then util.printout(rockspec_file) |
@@ -121,6 +121,12 @@ function show.command(flags, name, version) | |||
121 | if descript.homepage then | 121 | if descript.homepage then |
122 | util.printout("Homepage: ", descript.homepage) | 122 | util.printout("Homepage: ", descript.homepage) |
123 | end | 123 | end |
124 | if descript.issues_url then | ||
125 | util.printout("Issues: ", descript.issues_url) | ||
126 | end | ||
127 | if descript.labels then | ||
128 | util.printout("Labels: ", table.concat(descript.labels, ", ")) | ||
129 | end | ||
124 | util.printout("Installed in: ", path.rocks_tree_to_string(repo)) | 130 | util.printout("Installed in: ", path.rocks_tree_to_string(repo)) |
125 | 131 | ||
126 | if next(minfo.commands) then | 132 | if next(minfo.commands) then |
@@ -141,7 +147,7 @@ function show.command(flags, name, version) | |||
141 | util.printout("Depends on:") | 147 | util.printout("Depends on:") |
142 | for _, dep in ipairs(rockspec.dependencies) do | 148 | for _, dep in ipairs(rockspec.dependencies) do |
143 | direct_deps[dep.name] = true | 149 | direct_deps[dep.name] = true |
144 | util.printout("\t"..deps.show_dep(dep).." "..installed_rock_label(dep.name, flags["tree"])) | 150 | util.printout("\t"..vers.show_dep(dep).." "..installed_rock_label(dep.name, flags["tree"])) |
145 | end | 151 | end |
146 | end | 152 | end |
147 | local has_indirect_deps | 153 | local has_indirect_deps |
diff --git a/src/luarocks/unpack.lua b/src/luarocks/cmd/unpack.lua index 0922f9b9..c50701b0 100644 --- a/src/luarocks/unpack.lua +++ b/src/luarocks/cmd/unpack.lua | |||
@@ -2,16 +2,14 @@ | |||
2 | --- Module implementing the LuaRocks "unpack" command. | 2 | --- Module implementing the LuaRocks "unpack" command. |
3 | -- Unpack the contents of a rock. | 3 | -- Unpack the contents of a rock. |
4 | local unpack = {} | 4 | local unpack = {} |
5 | package.loaded["luarocks.unpack"] = unpack | ||
6 | 5 | ||
7 | local fetch = require("luarocks.fetch") | 6 | local fetch = require("luarocks.fetch") |
8 | local fs = require("luarocks.fs") | 7 | local fs = require("luarocks.fs") |
9 | local util = require("luarocks.util") | 8 | local util = require("luarocks.util") |
10 | local build = require("luarocks.build") | 9 | local build = require("luarocks.build") |
11 | local dir = require("luarocks.dir") | 10 | local dir = require("luarocks.dir") |
12 | local cfg = require("luarocks.cfg") | 11 | local cfg = require("luarocks.core.cfg") |
13 | 12 | ||
14 | util.add_run_function(unpack) | ||
15 | unpack.help_summary = "Unpack the contents of a rock." | 13 | unpack.help_summary = "Unpack the contents of a rock." |
16 | unpack.help_arguments = "[--force] {<rock>|<name> [<version>]}" | 14 | unpack.help_arguments = "[--force] {<rock>|<name> [<version>]}" |
17 | unpack.help = [[ | 15 | unpack.help = [[ |
diff --git a/src/luarocks/upload.lua b/src/luarocks/cmd/upload.lua index 7c0c416c..baee47ab 100644 --- a/src/luarocks/upload.lua +++ b/src/luarocks/cmd/upload.lua | |||
@@ -4,10 +4,9 @@ local upload = {} | |||
4 | local util = require("luarocks.util") | 4 | local util = require("luarocks.util") |
5 | local fetch = require("luarocks.fetch") | 5 | local fetch = require("luarocks.fetch") |
6 | local pack = require("luarocks.pack") | 6 | local pack = require("luarocks.pack") |
7 | local cfg = require("luarocks.cfg") | 7 | local cfg = require("luarocks.core.cfg") |
8 | local Api = require("luarocks.upload.api") | 8 | local Api = require("luarocks.upload.api") |
9 | 9 | ||
10 | util.add_run_function(upload) | ||
11 | upload.help_summary = "Upload a rockspec to the public rocks repository." | 10 | upload.help_summary = "Upload a rockspec to the public rocks repository." |
12 | upload.help_arguments = "[--skip-pack] [--api-key=<key>] [--force] <rockspec>" | 11 | upload.help_arguments = "[--skip-pack] [--api-key=<key>] [--force] <rockspec>" |
13 | upload.help = [[ | 12 | upload.help = [[ |
diff --git a/src/luarocks/write_rockspec.lua b/src/luarocks/cmd/write_rockspec.lua index 33edeb1b..73010f08 100644 --- a/src/luarocks/write_rockspec.lua +++ b/src/luarocks/cmd/write_rockspec.lua | |||
@@ -1,8 +1,7 @@ | |||
1 | 1 | ||
2 | local write_rockspec = {} | 2 | local write_rockspec = {} |
3 | package.loaded["luarocks.write_rockspec"] = write_rockspec | ||
4 | 3 | ||
5 | local cfg = require("luarocks.cfg") | 4 | local cfg = require("luarocks.core.cfg") |
6 | local dir = require("luarocks.dir") | 5 | local dir = require("luarocks.dir") |
7 | local fetch = require("luarocks.fetch") | 6 | local fetch = require("luarocks.fetch") |
8 | local fs = require("luarocks.fs") | 7 | local fs = require("luarocks.fs") |
@@ -10,8 +9,8 @@ local path = require("luarocks.path") | |||
10 | local persist = require("luarocks.persist") | 9 | local persist = require("luarocks.persist") |
11 | local type_check = require("luarocks.type_check") | 10 | local type_check = require("luarocks.type_check") |
12 | local util = require("luarocks.util") | 11 | local util = require("luarocks.util") |
12 | local vers = require("luarocks.vers") | ||
13 | 13 | ||
14 | util.add_run_function(write_rockspec) | ||
15 | write_rockspec.help_summary = "Write a template for a rockspec file." | 14 | write_rockspec.help_summary = "Write a template for a rockspec file." |
16 | write_rockspec.help_arguments = "[--output=<file> ...] [<name>] [<version>] [<url>|<path>]" | 15 | write_rockspec.help_arguments = "[--output=<file> ...] [<name>] [<version>] [<url>|<path>]" |
17 | write_rockspec.help = [[ | 16 | write_rockspec.help = [[ |
@@ -223,6 +222,7 @@ local function rockspec_cleanup(rockspec) | |||
223 | rockspec.source.protocol = nil | 222 | rockspec.source.protocol = nil |
224 | rockspec.variables = nil | 223 | rockspec.variables = nil |
225 | rockspec.name = nil | 224 | rockspec.name = nil |
225 | rockspec.format_is_at_least = nil | ||
226 | end | 226 | end |
227 | 227 | ||
228 | function write_rockspec.command(flags, name, version, url_or_dir) | 228 | function write_rockspec.command(flags, name, version, url_or_dir) |
@@ -285,6 +285,7 @@ function write_rockspec.command(flags, name, version, url_or_dir) | |||
285 | } | 285 | } |
286 | path.configure_paths(rockspec) | 286 | path.configure_paths(rockspec) |
287 | rockspec.source.protocol = protocol | 287 | rockspec.source.protocol = protocol |
288 | rockspec.format_is_at_least = vers.format_is_at_least | ||
288 | 289 | ||
289 | configure_lua_version(rockspec, flags["lua-version"]) | 290 | configure_lua_version(rockspec, flags["lua-version"]) |
290 | 291 | ||
diff --git a/src/luarocks/command_line.lua b/src/luarocks/command_line.lua index ac5ccd35..6a1cc519 100644 --- a/src/luarocks/command_line.lua +++ b/src/luarocks/command_line.lua | |||
@@ -5,7 +5,7 @@ local command_line = {} | |||
5 | local unpack = unpack or table.unpack | 5 | local unpack = unpack or table.unpack |
6 | 6 | ||
7 | local util = require("luarocks.util") | 7 | local util = require("luarocks.util") |
8 | local cfg = require("luarocks.cfg") | 8 | local cfg = require("luarocks.core.cfg") |
9 | local path = require("luarocks.path") | 9 | local path = require("luarocks.path") |
10 | local dir = require("luarocks.dir") | 10 | local dir = require("luarocks.dir") |
11 | local deps = require("luarocks.deps") | 11 | local deps = require("luarocks.deps") |
diff --git a/src/luarocks/cfg.lua b/src/luarocks/core/cfg.lua index 858a87fe..250f503e 100644 --- a/src/luarocks/cfg.lua +++ b/src/luarocks/core/cfg.lua | |||
@@ -1,3 +1,4 @@ | |||
1 | |||
1 | --- Configuration for LuaRocks. | 2 | --- Configuration for LuaRocks. |
2 | -- Tries to load the user's configuration file and | 3 | -- Tries to load the user's configuration file and |
3 | -- defines defaults for unset values. See the | 4 | -- defines defaults for unset values. See the |
@@ -12,11 +13,7 @@ | |||
12 | local rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs, package, tonumber, type, assert, _VERSION = | 13 | local rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs, package, tonumber, type, assert, _VERSION = |
13 | rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs, package, tonumber, type, assert, _VERSION | 14 | rawset, next, table, pairs, require, io, os, setmetatable, pcall, ipairs, package, tonumber, type, assert, _VERSION |
14 | 15 | ||
15 | --module("luarocks.cfg") | ||
16 | local cfg = {} | 16 | local cfg = {} |
17 | package.loaded["luarocks.cfg"] = cfg | ||
18 | |||
19 | local util = require("luarocks.util") | ||
20 | 17 | ||
21 | cfg.lua_version = _VERSION:match(" (5%.[123])$") or "5.1" | 18 | cfg.lua_version = _VERSION:match(" (5%.[123])$") or "5.1" |
22 | local version_suffix = cfg.lua_version:gsub("%.", "_") | 19 | local version_suffix = cfg.lua_version:gsub("%.", "_") |
@@ -31,15 +28,18 @@ if not ok then | |||
31 | site_config = {} | 28 | site_config = {} |
32 | end | 29 | end |
33 | 30 | ||
31 | local util = require("luarocks.core.util") | ||
32 | local persist = require("luarocks.core.persist") | ||
33 | local require = nil | ||
34 | -------------------------------------------------------------------------------- | ||
35 | |||
34 | cfg.program_version = "scm" | 36 | cfg.program_version = "scm" |
35 | cfg.program_series = "2.2" | 37 | cfg.program_series = "3.0" |
36 | cfg.major_version = (cfg.program_version:match("([^.]%.[^.])")) or cfg.program_series | 38 | cfg.major_version = (cfg.program_version:match("([^.]%.[^.])")) or cfg.program_series |
37 | cfg.variables = {} | 39 | cfg.variables = {} |
38 | cfg.rocks_trees = {} | 40 | cfg.rocks_trees = {} |
39 | cfg.platforms = {} | 41 | cfg.platforms = {} |
40 | 42 | ||
41 | local persist = require("luarocks.persist") | ||
42 | |||
43 | cfg.errorcodes = setmetatable({ | 43 | cfg.errorcodes = setmetatable({ |
44 | OK = 0, | 44 | OK = 0, |
45 | UNSPECIFIED = 1, | 45 | UNSPECIFIED = 1, |
@@ -75,8 +75,8 @@ end | |||
75 | -- so that this detection does not run every time. When it is | 75 | -- so that this detection does not run every time. When it is |
76 | -- performed, we use the Unix way to identify the system, | 76 | -- performed, we use the Unix way to identify the system, |
77 | -- even on Windows (assuming UnxUtils or Cygwin). | 77 | -- even on Windows (assuming UnxUtils or Cygwin). |
78 | local system = site_config.LUAROCKS_UNAME_S or io.popen("uname -s"):read("*l") | 78 | local system = site_config.LUAROCKS_UNAME_S or util.popen_read("uname -s") |
79 | local proc = site_config.LUAROCKS_UNAME_M or io.popen("uname -m"):read("*l") | 79 | local proc = site_config.LUAROCKS_UNAME_M or util.popen_read("uname -m") |
80 | if proc:match("i[%d]86") then | 80 | if proc:match("i[%d]86") then |
81 | cfg.target_cpu = "x86" | 81 | cfg.target_cpu = "x86" |
82 | elseif proc:match("amd64") or proc:match("x86_64") then | 82 | elseif proc:match("amd64") or proc:match("x86_64") then |
@@ -370,6 +370,8 @@ local defaults = { | |||
370 | MAKE = "make", | 370 | MAKE = "make", |
371 | CC = "cc", | 371 | CC = "cc", |
372 | LD = "ld", | 372 | LD = "ld", |
373 | AR = "ar", | ||
374 | RANLIB = "ranlib", | ||
373 | 375 | ||
374 | CVS = "cvs", | 376 | CVS = "cvs", |
375 | GIT = "git", | 377 | GIT = "git", |
@@ -426,7 +428,8 @@ local defaults = { | |||
426 | include = "include" | 428 | include = "include" |
427 | }, | 429 | }, |
428 | 430 | ||
429 | rocks_provided = {} | 431 | rocks_provided = {}, |
432 | rocks_provided_3_0 = {}, | ||
430 | } | 433 | } |
431 | 434 | ||
432 | if cfg.platforms.windows then | 435 | if cfg.platforms.windows then |
@@ -438,6 +441,7 @@ if cfg.platforms.windows then | |||
438 | defaults.arch = "win32-"..cfg.target_cpu | 441 | defaults.arch = "win32-"..cfg.target_cpu |
439 | defaults.lib_extension = "dll" | 442 | defaults.lib_extension = "dll" |
440 | defaults.external_lib_extension = "dll" | 443 | defaults.external_lib_extension = "dll" |
444 | defaults.static_lib_extension = "lib" | ||
441 | defaults.obj_extension = "obj" | 445 | defaults.obj_extension = "obj" |
442 | defaults.external_deps_dirs = { "c:/external/" } | 446 | defaults.external_deps_dirs = { "c:/external/" } |
443 | defaults.variables.LUA_BINDIR = site_config.LUA_BINDIR and site_config.LUA_BINDIR:gsub("\\", "/") or "c:/lua"..cfg.lua_version.."/bin" | 447 | defaults.variables.LUA_BINDIR = site_config.LUA_BINDIR and site_config.LUA_BINDIR:gsub("\\", "/") or "c:/lua"..cfg.lua_version.."/bin" |
@@ -451,6 +455,7 @@ if cfg.platforms.windows then | |||
451 | defaults.variables.WRAPPER = full_prefix.."\\rclauncher.c" | 455 | defaults.variables.WRAPPER = full_prefix.."\\rclauncher.c" |
452 | defaults.variables.LD = "link" | 456 | defaults.variables.LD = "link" |
453 | defaults.variables.MT = "mt" | 457 | defaults.variables.MT = "mt" |
458 | defaults.variables.AR = "lib" | ||
454 | defaults.variables.LUALIB = "lua"..cfg.lua_version..".lib" | 459 | defaults.variables.LUALIB = "lua"..cfg.lua_version..".lib" |
455 | defaults.variables.CFLAGS = "/nologo /MD /O2" | 460 | defaults.variables.CFLAGS = "/nologo /MD /O2" |
456 | defaults.variables.LIBFLAG = "/nologo /dll" | 461 | defaults.variables.LIBFLAG = "/nologo /dll" |
@@ -490,11 +495,14 @@ end | |||
490 | 495 | ||
491 | if cfg.platforms.mingw32 then | 496 | if cfg.platforms.mingw32 then |
492 | defaults.obj_extension = "o" | 497 | defaults.obj_extension = "o" |
498 | defaults.static_lib_extension = "a" | ||
493 | defaults.cmake_generator = "MinGW Makefiles" | 499 | defaults.cmake_generator = "MinGW Makefiles" |
494 | defaults.variables.MAKE = "mingw32-make" | 500 | defaults.variables.MAKE = "mingw32-make" |
495 | defaults.variables.CC = "mingw32-gcc" | 501 | defaults.variables.CC = "mingw32-gcc" |
496 | defaults.variables.RC = "windres" | 502 | defaults.variables.RC = "windres" |
497 | defaults.variables.LD = "mingw32-gcc" | 503 | defaults.variables.LD = "mingw32-gcc" |
504 | defaults.variables.AR = "ar" | ||
505 | defaults.variables.RANLIB = "ranlib" | ||
498 | defaults.variables.CFLAGS = "-O2" | 506 | defaults.variables.CFLAGS = "-O2" |
499 | defaults.variables.LIBFLAG = "-shared" | 507 | defaults.variables.LIBFLAG = "-shared" |
500 | defaults.makefile = "Makefile" | 508 | defaults.makefile = "Makefile" |
@@ -515,6 +523,7 @@ end | |||
515 | 523 | ||
516 | if cfg.platforms.unix then | 524 | if cfg.platforms.unix then |
517 | defaults.lib_extension = "so" | 525 | defaults.lib_extension = "so" |
526 | defaults.static_lib_extension = "a" | ||
518 | defaults.external_lib_extension = "so" | 527 | defaults.external_lib_extension = "so" |
519 | defaults.obj_extension = "o" | 528 | defaults.obj_extension = "o" |
520 | defaults.external_deps_dirs = { "/usr/local", "/usr" } | 529 | defaults.external_deps_dirs = { "/usr/local", "/usr" } |
@@ -589,7 +598,7 @@ if cfg.platforms.macosx then | |||
589 | defaults.variables.LIBFLAG = "-bundle -undefined dynamic_lookup -all_load" | 598 | defaults.variables.LIBFLAG = "-bundle -undefined dynamic_lookup -all_load" |
590 | defaults.variables.STAT = "/usr/bin/stat" | 599 | defaults.variables.STAT = "/usr/bin/stat" |
591 | defaults.variables.STATFLAG = "-f '%A'" | 600 | defaults.variables.STATFLAG = "-f '%A'" |
592 | local version = io.popen("sw_vers -productVersion"):read("*l") | 601 | local version = util.popen_read("sw_vers -productVersion") |
593 | version = tonumber(version and version:match("^[^.]+%.([^.]+)")) or 3 | 602 | version = tonumber(version and version:match("^[^.]+%.([^.]+)")) or 3 |
594 | if version >= 10 then | 603 | if version >= 10 then |
595 | version = 8 | 604 | version = 8 |
@@ -648,8 +657,8 @@ end | |||
648 | if package.loaded.jit then | 657 | if package.loaded.jit then |
649 | -- LuaJIT | 658 | -- LuaJIT |
650 | local lj_version = package.loaded.jit.version:match("LuaJIT (.*)"):gsub("%-","") | 659 | local lj_version = package.loaded.jit.version:match("LuaJIT (.*)"):gsub("%-","") |
651 | --defaults.rocks_provided["luajit"] = lj_version.."-1" | ||
652 | defaults.rocks_provided["luabitop"] = lj_version.."-1" | 660 | defaults.rocks_provided["luabitop"] = lj_version.."-1" |
661 | defaults.rocks_provided_3_0["luajit"] = lj_version.."-1" | ||
653 | end | 662 | end |
654 | 663 | ||
655 | -- Use defaults: | 664 | -- Use defaults: |
@@ -666,6 +675,7 @@ for _, entry in ipairs({"variables", "rocks_provided"}) do | |||
666 | end | 675 | end |
667 | end | 676 | end |
668 | end | 677 | end |
678 | setmetatable(defaults.rocks_provided_3_0, { __index = cfg.rocks_provided }) | ||
669 | 679 | ||
670 | -- For values not set in the config file, use values from the 'defaults' table. | 680 | -- For values not set in the config file, use values from the 'defaults' table. |
671 | local cfg_mt = { | 681 | local cfg_mt = { |
diff --git a/src/luarocks/core/dir.lua b/src/luarocks/core/dir.lua new file mode 100644 index 00000000..05b2c72d --- /dev/null +++ b/src/luarocks/core/dir.lua | |||
@@ -0,0 +1,43 @@ | |||
1 | |||
2 | local dir = {} | ||
3 | |||
4 | local require = nil | ||
5 | -------------------------------------------------------------------------------- | ||
6 | |||
7 | dir.separator = "/" | ||
8 | |||
9 | --- Describe a path in a cross-platform way. | ||
10 | -- Use this function to avoid platform-specific directory | ||
11 | -- separators in other modules. Removes trailing slashes from | ||
12 | -- each component given, to avoid repeated separators. | ||
13 | -- Separators inside strings are kept, to handle URLs containing | ||
14 | -- protocols. | ||
15 | -- @param ... strings representing directories | ||
16 | -- @return string: a string with a platform-specific representation | ||
17 | -- of the path. | ||
18 | function dir.path(...) | ||
19 | local t = {...} | ||
20 | while t[1] == "" do | ||
21 | table.remove(t, 1) | ||
22 | end | ||
23 | return (table.concat(t, "/"):gsub("([^:])/+", "%1/"):gsub("^/+", "/"):gsub("/*$", "")) | ||
24 | end | ||
25 | |||
26 | --- Split protocol and path from an URL or local pathname. | ||
27 | -- URLs should be in the "protocol://path" format. | ||
28 | -- For local pathnames, "file" is returned as the protocol. | ||
29 | -- @param url string: an URL or a local pathname. | ||
30 | -- @return string, string: the protocol, and the pathname without the protocol. | ||
31 | function dir.split_url(url) | ||
32 | assert(type(url) == "string") | ||
33 | |||
34 | local protocol, pathname = url:match("^([^:]*)://(.*)") | ||
35 | if not protocol then | ||
36 | protocol = "file" | ||
37 | pathname = url | ||
38 | end | ||
39 | return protocol, pathname | ||
40 | end | ||
41 | |||
42 | return dir | ||
43 | |||
diff --git a/src/luarocks/manif_core.lua b/src/luarocks/core/manif.lua index 82e7ea4d..549cfb4c 100644 --- a/src/luarocks/manif_core.lua +++ b/src/luarocks/core/manif.lua | |||
@@ -1,15 +1,13 @@ | |||
1 | 1 | ||
2 | --- Core functions for querying manifest files. | 2 | --- Core functions for querying manifest files. |
3 | -- This module requires no specific 'fs' functionality. | 3 | local manif = {} |
4 | local manif_core = {} | ||
5 | package.loaded["luarocks.manif_core"] = manif_core | ||
6 | 4 | ||
7 | local persist = require("luarocks.persist") | 5 | local persist = require("luarocks.core.persist") |
8 | local type_check = require("luarocks.type_check") | 6 | local type_check = require("luarocks.core.type_check") |
9 | local cfg = require("luarocks.cfg") | 7 | local cfg = require("luarocks.core.cfg") |
10 | local dir = require("luarocks.dir") | 8 | local dir = require("luarocks.core.dir") |
11 | local util = require("luarocks.util") | 9 | local require = nil |
12 | local path = require("luarocks.path") | 10 | -------------------------------------------------------------------------------- |
13 | 11 | ||
14 | -- Table with repository identifiers as keys and tables mapping | 12 | -- Table with repository identifiers as keys and tables mapping |
15 | -- Lua versions to cached loaded manifests as values. | 13 | -- Lua versions to cached loaded manifests as values. |
@@ -19,7 +17,7 @@ local manifest_cache = {} | |||
19 | -- @param repo_url string: The repository identifier. | 17 | -- @param repo_url string: The repository identifier. |
20 | -- @param lua_version string: Lua version in "5.x" format, defaults to installed version. | 18 | -- @param lua_version string: Lua version in "5.x" format, defaults to installed version. |
21 | -- @param manifest table: the manifest to be cached. | 19 | -- @param manifest table: the manifest to be cached. |
22 | function manif_core.cache_manifest(repo_url, lua_version, manifest) | 20 | function manif.cache_manifest(repo_url, lua_version, manifest) |
23 | lua_version = lua_version or cfg.lua_version | 21 | lua_version = lua_version or cfg.lua_version |
24 | manifest_cache[repo_url] = manifest_cache[repo_url] or {} | 22 | manifest_cache[repo_url] = manifest_cache[repo_url] or {} |
25 | manifest_cache[repo_url][lua_version] = manifest | 23 | manifest_cache[repo_url][lua_version] = manifest |
@@ -29,7 +27,7 @@ end | |||
29 | -- @param repo_url string: The repository identifier. | 27 | -- @param repo_url string: The repository identifier. |
30 | -- @param lua_version string: Lua version in "5.x" format, defaults to installed version. | 28 | -- @param lua_version string: Lua version in "5.x" format, defaults to installed version. |
31 | -- @return table or nil: loaded manifest or nil if cache is empty. | 29 | -- @return table or nil: loaded manifest or nil if cache is empty. |
32 | function manif_core.get_cached_manifest(repo_url, lua_version) | 30 | function manif.get_cached_manifest(repo_url, lua_version) |
33 | lua_version = lua_version or cfg.lua_version | 31 | lua_version = lua_version or cfg.lua_version |
34 | return manifest_cache[repo_url] and manifest_cache[repo_url][lua_version] | 32 | return manifest_cache[repo_url] and manifest_cache[repo_url][lua_version] |
35 | end | 33 | end |
@@ -42,7 +40,7 @@ end | |||
42 | -- @param quick boolean: If given, skips type checking. | 40 | -- @param quick boolean: If given, skips type checking. |
43 | -- @return table or (nil, string, string): the manifest or nil, | 41 | -- @return table or (nil, string, string): the manifest or nil, |
44 | -- error message and error code ("open", "load", "run" or "type"). | 42 | -- error message and error code ("open", "load", "run" or "type"). |
45 | function manif_core.manifest_loader(file, repo_url, lua_version, quick) | 43 | function manif.manifest_loader(file, repo_url, lua_version, quick) |
46 | local manifest, err, errcode = persist.load_into_table(file) | 44 | local manifest, err, errcode = persist.load_into_table(file) |
47 | if not manifest then | 45 | if not manifest then |
48 | return nil, "Failed loading manifest for "..repo_url..": "..err, errcode | 46 | return nil, "Failed loading manifest for "..repo_url..": "..err, errcode |
@@ -55,7 +53,7 @@ function manif_core.manifest_loader(file, repo_url, lua_version, quick) | |||
55 | end | 53 | end |
56 | end | 54 | end |
57 | 55 | ||
58 | manif_core.cache_manifest(repo_url, lua_version, manifest) | 56 | manif.cache_manifest(repo_url, lua_version, manifest) |
59 | return manifest | 57 | return manifest |
60 | end | 58 | end |
61 | 59 | ||
@@ -65,42 +63,16 @@ end | |||
65 | -- @param repo_url string: URL or pathname for the repository. | 63 | -- @param repo_url string: URL or pathname for the repository. |
66 | -- @return table or (nil, string, string): A table representing the manifest, | 64 | -- @return table or (nil, string, string): A table representing the manifest, |
67 | -- or nil followed by an error message and an error code, see manifest_loader. | 65 | -- or nil followed by an error message and an error code, see manifest_loader. |
68 | function manif_core.load_local_manifest(repo_url) | 66 | function manif.load_local_manifest(repo_url) |
69 | assert(type(repo_url) == "string") | 67 | assert(type(repo_url) == "string") |
70 | 68 | ||
71 | local cached_manifest = manif_core.get_cached_manifest(repo_url) | 69 | local cached_manifest = manif.get_cached_manifest(repo_url) |
72 | if cached_manifest then | 70 | if cached_manifest then |
73 | return cached_manifest | 71 | return cached_manifest |
74 | end | 72 | end |
75 | 73 | ||
76 | local pathname = dir.path(repo_url, "manifest") | 74 | local pathname = dir.path(repo_url, "manifest") |
77 | return manif_core.manifest_loader(pathname, repo_url, nil, true) | 75 | return manif.manifest_loader(pathname, repo_url, nil, true) |
78 | end | 76 | end |
79 | 77 | ||
80 | --- Get all versions of a package listed in a manifest file. | 78 | return manif |
81 | -- @param name string: a package name. | ||
82 | -- @param deps_mode string: "one", to use only the currently | ||
83 | -- configured tree; "order" to select trees based on order | ||
84 | -- (use the current tree and all trees below it on the list) | ||
85 | -- or "all", to use all trees. | ||
86 | -- @return table: An array of strings listing installed | ||
87 | -- versions of a package. | ||
88 | function manif_core.get_versions(name, deps_mode) | ||
89 | assert(type(name) == "string") | ||
90 | assert(type(deps_mode) == "string") | ||
91 | |||
92 | local version_set = {} | ||
93 | path.map_trees(deps_mode, function(tree) | ||
94 | local manifest = manif_core.load_local_manifest(path.rocks_dir(tree)) | ||
95 | |||
96 | if manifest and manifest.repository[name] then | ||
97 | for version in pairs(manifest.repository[name]) do | ||
98 | version_set[version] = true | ||
99 | end | ||
100 | end | ||
101 | end) | ||
102 | |||
103 | return util.keys(version_set) | ||
104 | end | ||
105 | |||
106 | return manif_core | ||
diff --git a/src/luarocks/core/path.lua b/src/luarocks/core/path.lua new file mode 100644 index 00000000..ed85aeac --- /dev/null +++ b/src/luarocks/core/path.lua | |||
@@ -0,0 +1,114 @@ | |||
1 | |||
2 | --- Core LuaRocks-specific path handling functions. | ||
3 | local path = {} | ||
4 | |||
5 | local cfg = require("luarocks.core.cfg") | ||
6 | local dir = require("luarocks.core.dir") | ||
7 | local require = nil | ||
8 | -------------------------------------------------------------------------------- | ||
9 | |||
10 | function path.rocks_dir(tree) | ||
11 | if type(tree) == "string" then | ||
12 | return dir.path(tree, cfg.rocks_subdir) | ||
13 | else | ||
14 | assert(type(tree) == "table") | ||
15 | return tree.rocks_dir or dir.path(tree.root, cfg.rocks_subdir) | ||
16 | end | ||
17 | end | ||
18 | |||
19 | --- Produce a versioned version of a filename. | ||
20 | -- @param file string: filename (must start with prefix) | ||
21 | -- @param prefix string: Path prefix for file | ||
22 | -- @param name string: Rock name | ||
23 | -- @param version string: Rock version | ||
24 | -- @return string: a pathname with the same directory parts and a versioned basename. | ||
25 | function path.versioned_name(file, prefix, name, version) | ||
26 | assert(type(file) == "string") | ||
27 | assert(type(name) == "string") | ||
28 | assert(type(version) == "string") | ||
29 | |||
30 | local rest = file:sub(#prefix+1):gsub("^/*", "") | ||
31 | local name_version = (name.."_"..version):gsub("%-", "_"):gsub("%.", "_") | ||
32 | return dir.path(prefix, name_version.."-"..rest) | ||
33 | end | ||
34 | |||
35 | --- Convert a pathname to a module identifier. | ||
36 | -- In Unix, for example, a path "foo/bar/baz.lua" is converted to | ||
37 | -- "foo.bar.baz"; "bla/init.lua" returns "bla"; "foo.so" returns "foo". | ||
38 | -- @param file string: Pathname of module | ||
39 | -- @return string: The module identifier, or nil if given path is | ||
40 | -- not a conformant module path (the function does not check if the | ||
41 | -- path actually exists). | ||
42 | function path.path_to_module(file) | ||
43 | assert(type(file) == "string") | ||
44 | |||
45 | local name = file:match("(.*)%."..cfg.lua_extension.."$") | ||
46 | if name then | ||
47 | name = name:gsub(dir.separator, ".") | ||
48 | local init = name:match("(.*)%.init$") | ||
49 | if init then | ||
50 | name = init | ||
51 | end | ||
52 | else | ||
53 | name = file:match("(.*)%."..cfg.lib_extension.."$") | ||
54 | if name then | ||
55 | name = name:gsub(dir.separator, ".") | ||
56 | --[[ TODO disable static libs until we fix the conflict in the manifest, which will take extending the manifest format. | ||
57 | else | ||
58 | name = file:match("(.*)%."..cfg.static_lib_extension.."$") | ||
59 | if name then | ||
60 | name = name:gsub(dir.separator, ".") | ||
61 | end | ||
62 | ]] | ||
63 | end | ||
64 | end | ||
65 | if not name then name = file end | ||
66 | name = name:gsub("^%.+", ""):gsub("%.+$", "") | ||
67 | return name | ||
68 | end | ||
69 | |||
70 | function path.deploy_lua_dir(tree) | ||
71 | if type(tree) == "string" then | ||
72 | return dir.path(tree, cfg.lua_modules_path) | ||
73 | else | ||
74 | assert(type(tree) == "table") | ||
75 | return tree.lua_dir or dir.path(tree.root, cfg.lua_modules_path) | ||
76 | end | ||
77 | end | ||
78 | |||
79 | function path.deploy_lib_dir(tree) | ||
80 | if type(tree) == "string" then | ||
81 | return dir.path(tree, cfg.lib_modules_path) | ||
82 | else | ||
83 | assert(type(tree) == "table") | ||
84 | return tree.lib_dir or dir.path(tree.root, cfg.lib_modules_path) | ||
85 | end | ||
86 | end | ||
87 | |||
88 | local is_src_extension = { [".lua"] = true, [".tl"] = true, [".tld"] = true, [".moon"] = true } | ||
89 | |||
90 | --- Return the pathname of the file that would be loaded for a module, indexed. | ||
91 | -- @param file_name string: module file name as in manifest (eg. "socket/core.so") | ||
92 | -- @param name string: name of the package (eg. "luasocket") | ||
93 | -- @param version string: version number (eg. "2.0.2-1") | ||
94 | -- @param tree string: repository path (eg. "/usr/local") | ||
95 | -- @param i number: the index, 1 if version is the current default, > 1 otherwise. | ||
96 | -- This is done this way for use by select_module in luarocks.loader. | ||
97 | -- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so") | ||
98 | function path.which_i(file_name, name, version, tree, i) | ||
99 | local deploy_dir | ||
100 | local extension = file_name:match("%.[a-z]+$") | ||
101 | if is_src_extension[extension] then | ||
102 | deploy_dir = path.deploy_lua_dir(tree) | ||
103 | file_name = dir.path(deploy_dir, file_name) | ||
104 | else | ||
105 | deploy_dir = path.deploy_lib_dir(tree) | ||
106 | file_name = dir.path(deploy_dir, file_name) | ||
107 | end | ||
108 | if i > 1 then | ||
109 | file_name = path.versioned_name(file_name, deploy_dir, name, version) | ||
110 | end | ||
111 | return file_name | ||
112 | end | ||
113 | |||
114 | return path | ||
diff --git a/src/luarocks/core/persist.lua b/src/luarocks/core/persist.lua new file mode 100644 index 00000000..48979184 --- /dev/null +++ b/src/luarocks/core/persist.lua | |||
@@ -0,0 +1,81 @@ | |||
1 | |||
2 | local persist = {} | ||
3 | |||
4 | local require = nil | ||
5 | -------------------------------------------------------------------------------- | ||
6 | |||
7 | --- Load and run a Lua file in an environment. | ||
8 | -- @param filename string: the name of the file. | ||
9 | -- @param env table: the environment table. | ||
10 | -- @return (true, any) or (nil, string, string): true and the return value | ||
11 | -- of the file, or nil, an error message and an error code ("open", "load" | ||
12 | -- or "run") in case of errors. | ||
13 | local function run_file(filename, env) | ||
14 | local fd, err = io.open(filename) | ||
15 | if not fd then | ||
16 | return nil, err, "open" | ||
17 | end | ||
18 | local str, err = fd:read("*a") | ||
19 | fd:close() | ||
20 | if not str then | ||
21 | return nil, err, "open" | ||
22 | end | ||
23 | str = str:gsub("^#![^\n]*\n", "") | ||
24 | local chunk, ran | ||
25 | if _VERSION == "Lua 5.1" then -- Lua 5.1 | ||
26 | chunk, err = loadstring(str, filename) | ||
27 | if chunk then | ||
28 | setfenv(chunk, env) | ||
29 | ran, err = pcall(chunk) | ||
30 | end | ||
31 | else -- Lua 5.2 | ||
32 | chunk, err = load(str, filename, "t", env) | ||
33 | if chunk then | ||
34 | ran, err = pcall(chunk) | ||
35 | end | ||
36 | end | ||
37 | if not chunk then | ||
38 | return nil, "Error loading file: "..err, "load" | ||
39 | end | ||
40 | if not ran then | ||
41 | return nil, "Error running file: "..err, "run" | ||
42 | end | ||
43 | return true, err | ||
44 | end | ||
45 | |||
46 | --- Load a Lua file containing assignments, storing them in a table. | ||
47 | -- The global environment is not propagated to the loaded file. | ||
48 | -- @param filename string: the name of the file. | ||
49 | -- @param tbl table or nil: if given, this table is used to store | ||
50 | -- loaded values. | ||
51 | -- @return (table, table) or (nil, string, string): a table with the file's assignments | ||
52 | -- as fields and set of undefined globals accessed in file, | ||
53 | -- or nil, an error message and an error code ("open"; couldn't open the file, | ||
54 | -- "load"; compile-time error, or "run"; run-time error) | ||
55 | -- in case of errors. | ||
56 | function persist.load_into_table(filename, tbl) | ||
57 | assert(type(filename) == "string") | ||
58 | assert(type(tbl) == "table" or not tbl) | ||
59 | |||
60 | local result = tbl or {} | ||
61 | local globals = {} | ||
62 | local globals_mt = { | ||
63 | __index = function(t, k) | ||
64 | globals[k] = true | ||
65 | end | ||
66 | } | ||
67 | local save_mt = getmetatable(result) | ||
68 | setmetatable(result, globals_mt) | ||
69 | |||
70 | local ok, err, errcode = run_file(filename, result) | ||
71 | |||
72 | setmetatable(result, save_mt) | ||
73 | |||
74 | if not ok then | ||
75 | return nil, err, errcode | ||
76 | end | ||
77 | return result, globals | ||
78 | end | ||
79 | |||
80 | return persist | ||
81 | |||
diff --git a/src/luarocks/core/type_check.lua b/src/luarocks/core/type_check.lua new file mode 100644 index 00000000..343b7154 --- /dev/null +++ b/src/luarocks/core/type_check.lua | |||
@@ -0,0 +1,229 @@ | |||
1 | |||
2 | local type_check = {} | ||
3 | |||
4 | local cfg = require("luarocks.core.cfg") | ||
5 | local vers = require("luarocks.core.vers") | ||
6 | local require = nil | ||
7 | -------------------------------------------------------------------------------- | ||
8 | |||
9 | type_check.string_1 = { _type = "string" } | ||
10 | type_check.number_1 = { _type = "number" } | ||
11 | type_check.mandatory_string_1 = { _type = "string", _mandatory = true } | ||
12 | |||
13 | local number_1 = type_check.number_1 | ||
14 | local string_1 = type_check.string_1 | ||
15 | local mandatory_string_1 = type_check.mandatory_string_1 | ||
16 | |||
17 | local manifest_types = { | ||
18 | repository = { | ||
19 | _mandatory = true, | ||
20 | -- packages | ||
21 | _any = { | ||
22 | -- versions | ||
23 | _any = { | ||
24 | -- items | ||
25 | _any = { | ||
26 | arch = mandatory_string_1, | ||
27 | modules = { _any = string_1 }, | ||
28 | commands = { _any = string_1 }, | ||
29 | dependencies = { _any = string_1 }, | ||
30 | -- TODO: to be extended with more metadata. | ||
31 | } | ||
32 | } | ||
33 | } | ||
34 | }, | ||
35 | modules = { | ||
36 | _mandatory = true, | ||
37 | -- modules | ||
38 | _any = { | ||
39 | -- providers | ||
40 | _any = string_1 | ||
41 | } | ||
42 | }, | ||
43 | commands = { | ||
44 | _mandatory = true, | ||
45 | -- modules | ||
46 | _any = { | ||
47 | -- commands | ||
48 | _any = string_1 | ||
49 | } | ||
50 | }, | ||
51 | dependencies = { | ||
52 | -- each module | ||
53 | _any = { | ||
54 | -- each version | ||
55 | _any = { | ||
56 | -- each dependency | ||
57 | _any = { | ||
58 | name = string_1, | ||
59 | constraints = { | ||
60 | _any = { | ||
61 | no_upgrade = { _type = "boolean" }, | ||
62 | op = string_1, | ||
63 | version = { | ||
64 | string = string_1, | ||
65 | _any = number_1, | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | } | ||
73 | } | ||
74 | |||
75 | local function check_version(version, typetbl, context) | ||
76 | local typetbl_version = typetbl._version or "1.0" | ||
77 | if vers.compare_versions(typetbl_version, version) then | ||
78 | if context == "" then | ||
79 | return nil, "Invalid rockspec_format version number in rockspec? Please fix rockspec accordingly." | ||
80 | else | ||
81 | return nil, context.." is not supported in rockspec format "..version.." (requires version "..typetbl_version.."), please fix the rockspec_format field accordingly." | ||
82 | end | ||
83 | end | ||
84 | return true | ||
85 | end | ||
86 | |||
87 | --- Type check an object. | ||
88 | -- The object is compared against an archetypical value | ||
89 | -- matching the expected type -- the actual values don't matter, | ||
90 | -- only their types. Tables are type checked recursively. | ||
91 | -- @param version string: The version of the item. | ||
92 | -- @param item any: The object being checked. | ||
93 | -- @param typetbl any: The type-checking table for the object. | ||
94 | -- @param context string: A string indicating the "context" where the | ||
95 | -- error occurred (the full table path), for error messages. | ||
96 | -- @return boolean or (nil, string): true if type checking | ||
97 | -- succeeded, or nil and an error message if it failed. | ||
98 | -- @see type_check_table | ||
99 | local function type_check_item(version, item, typetbl, context) | ||
100 | assert(type(version) == "string") | ||
101 | |||
102 | local ok, err = check_version(version, typetbl, context) | ||
103 | if not ok then | ||
104 | return nil, err | ||
105 | end | ||
106 | |||
107 | local item_type = type(item) or "nil" | ||
108 | local expected_type = typetbl._type or "table" | ||
109 | |||
110 | if expected_type == "number" then | ||
111 | if not tonumber(item) then | ||
112 | return nil, "Type mismatch on field "..context..": expected a number" | ||
113 | end | ||
114 | elseif expected_type == "string" then | ||
115 | if item_type ~= "string" then | ||
116 | return nil, "Type mismatch on field "..context..": expected a string, got "..item_type | ||
117 | end | ||
118 | if typetbl._pattern then | ||
119 | if not item:match("^"..typetbl._pattern.."$") then | ||
120 | return nil, "Type mismatch on field "..context..": invalid value "..item.." does not match '"..typetbl._pattern.."'" | ||
121 | end | ||
122 | end | ||
123 | elseif expected_type == "table" then | ||
124 | if item_type ~= expected_type then | ||
125 | return nil, "Type mismatch on field "..context..": expected a table" | ||
126 | else | ||
127 | return type_check.type_check_table(version, item, typetbl, context) | ||
128 | end | ||
129 | elseif item_type ~= expected_type then | ||
130 | return nil, "Type mismatch on field "..context..": expected "..expected_type | ||
131 | end | ||
132 | return true | ||
133 | end | ||
134 | |||
135 | local function mkfield(context, field) | ||
136 | if context == "" then | ||
137 | return tostring(field) | ||
138 | elseif type(field) == "string" then | ||
139 | return context.."."..field | ||
140 | else | ||
141 | return context.."["..tostring(field).."]" | ||
142 | end | ||
143 | end | ||
144 | |||
145 | --- Type check the contents of a table. | ||
146 | -- The table's contents are compared against a reference table, | ||
147 | -- which contains the recognized fields, with archetypical values | ||
148 | -- matching the expected types -- the actual values of items in the | ||
149 | -- reference table don't matter, only their types (ie, for field x | ||
150 | -- in tbl that is correctly typed, type(tbl.x) == type(types.x)). | ||
151 | -- If the reference table contains a field called MORE, then | ||
152 | -- unknown fields in the checked table are accepted. | ||
153 | -- If it contains a field called ANY, then its type will be | ||
154 | -- used to check any unknown fields. If a field is prefixed | ||
155 | -- with MUST_, it is mandatory; its absence from the table is | ||
156 | -- a type error. | ||
157 | -- Tables are type checked recursively. | ||
158 | -- @param version string: The version of tbl. | ||
159 | -- @param tbl table: The table to be type checked. | ||
160 | -- @param typetbl table: The type-checking table, containing | ||
161 | -- values for recognized fields in the checked table. | ||
162 | -- @param context string: A string indicating the "context" where the | ||
163 | -- error occurred (such as the name of the table the item is a part of), | ||
164 | -- to be used by error messages. | ||
165 | -- @return boolean or (nil, string): true if type checking | ||
166 | -- succeeded, or nil and an error message if it failed. | ||
167 | function type_check.type_check_table(version, tbl, typetbl, context) | ||
168 | assert(type(version) == "string") | ||
169 | assert(type(tbl) == "table") | ||
170 | assert(type(typetbl) == "table") | ||
171 | |||
172 | local ok, err = check_version(version, typetbl, context) | ||
173 | if not ok then | ||
174 | return nil, err | ||
175 | end | ||
176 | |||
177 | for k, v in pairs(tbl) do | ||
178 | local t = typetbl[k] or typetbl._any | ||
179 | if t then | ||
180 | local ok, err = type_check_item(version, v, t, mkfield(context, k)) | ||
181 | if not ok then return nil, err end | ||
182 | elseif typetbl._more then | ||
183 | -- Accept unknown field | ||
184 | else | ||
185 | if not cfg.accept_unknown_fields then | ||
186 | return nil, "Unknown field "..k | ||
187 | end | ||
188 | end | ||
189 | end | ||
190 | for k, v in pairs(typetbl) do | ||
191 | if k:sub(1,1) ~= "_" and v._mandatory then | ||
192 | if not tbl[k] then | ||
193 | return nil, "Mandatory field "..mkfield(context, k).." is missing." | ||
194 | end | ||
195 | end | ||
196 | end | ||
197 | return true | ||
198 | end | ||
199 | |||
200 | function type_check.check_undeclared_globals(globals, typetbl) | ||
201 | local undeclared = {} | ||
202 | for glob, _ in pairs(globals) do | ||
203 | if not (typetbl[glob] or typetbl["MUST_"..glob]) then | ||
204 | table.insert(undeclared, glob) | ||
205 | end | ||
206 | end | ||
207 | if #undeclared == 1 then | ||
208 | return nil, "Unknown variable: "..undeclared[1] | ||
209 | elseif #undeclared > 1 then | ||
210 | return nil, "Unknown variables: "..table.concat(undeclared, ", ") | ||
211 | end | ||
212 | return true | ||
213 | end | ||
214 | |||
215 | --- Type check a manifest table. | ||
216 | -- Verify the correctness of elements from a | ||
217 | -- manifest table, reporting on unknown fields and type | ||
218 | -- mismatches. | ||
219 | -- @return boolean or (nil, string): true if type checking | ||
220 | -- succeeded, or nil and an error message if it failed. | ||
221 | function type_check.type_check_manifest(manifest, globals) | ||
222 | assert(type(manifest) == "table") | ||
223 | local ok, err = type_check.check_undeclared_globals(globals, manifest_types) | ||
224 | if not ok then return nil, err end | ||
225 | return type_check.type_check_table("1.0", manifest, manifest_types, "") | ||
226 | end | ||
227 | |||
228 | return type_check | ||
229 | |||
diff --git a/src/luarocks/core/util.lua b/src/luarocks/core/util.lua new file mode 100644 index 00000000..85b59af6 --- /dev/null +++ b/src/luarocks/core/util.lua | |||
@@ -0,0 +1,272 @@ | |||
1 | |||
2 | local util = {} | ||
3 | |||
4 | local require = nil | ||
5 | -------------------------------------------------------------------------------- | ||
6 | |||
7 | --- Run a process and read a its output. | ||
8 | -- Equivalent to io.popen(cmd):read("*l"), except that it | ||
9 | -- closes the fd right away. | ||
10 | -- @param cmd string: The command to execute | ||
11 | -- @param spec string: "*l" by default, to read a single line. | ||
12 | -- May be used to read more, passing, for instance, "*a". | ||
13 | -- @return string: the output of the program. | ||
14 | function util.popen_read(cmd, spec) | ||
15 | local fd = io.popen(cmd) | ||
16 | local out = fd:read(spec or "*l") | ||
17 | fd:close() | ||
18 | return out | ||
19 | end | ||
20 | |||
21 | --- Create a new shallow copy of a table: a new table with | ||
22 | -- the same keys and values. Keys point to the same objects as | ||
23 | -- the original table (ie, does not copy recursively). | ||
24 | -- @param tbl table: the input table | ||
25 | -- @return table: a new table with the same contents. | ||
26 | function util.make_shallow_copy(tbl) | ||
27 | local copy = {} | ||
28 | for k,v in pairs(tbl) do | ||
29 | copy[k] = v | ||
30 | end | ||
31 | return copy | ||
32 | end | ||
33 | |||
34 | --- | ||
35 | -- Formats tables with cycles recursively to any depth. | ||
36 | -- References to other tables are shown as values. | ||
37 | -- Self references are indicated. | ||
38 | -- The string returned is "Lua code", which can be procesed | ||
39 | -- (in the case in which indent is composed by spaces or "--"). | ||
40 | -- Userdata and function keys and values are shown as strings, | ||
41 | -- which logically are exactly not equivalent to the original code. | ||
42 | -- This routine can serve for pretty formating tables with | ||
43 | -- proper indentations, apart from printing them: | ||
44 | -- io.write(table.show(t, "t")) -- a typical use | ||
45 | -- Written by Julio Manuel Fernandez-Diaz, | ||
46 | -- Heavily based on "Saving tables with cycles", PIL2, p. 113. | ||
47 | -- @param t table: is the table. | ||
48 | -- @param name string: is the name of the table (optional) | ||
49 | -- @param indent string: is a first indentation (optional). | ||
50 | -- @return string: the pretty-printed table | ||
51 | function util.show_table(t, name, indent) | ||
52 | local cart -- a container | ||
53 | local autoref -- for self references | ||
54 | |||
55 | local function is_empty_table(t) return next(t) == nil end | ||
56 | |||
57 | local function basic_serialize (o) | ||
58 | local so = tostring(o) | ||
59 | if type(o) == "function" then | ||
60 | local info = debug.getinfo(o, "S") | ||
61 | -- info.name is nil because o is not a calling level | ||
62 | if info.what == "C" then | ||
63 | return ("%q"):format(so .. ", C function") | ||
64 | else | ||
65 | -- the information is defined through lines | ||
66 | return ("%q"):format(so .. ", defined in (" .. info.linedefined .. "-" .. info.lastlinedefined .. ")" .. info.source) | ||
67 | end | ||
68 | elseif type(o) == "number" then | ||
69 | return so | ||
70 | else | ||
71 | return ("%q"):format(so) | ||
72 | end | ||
73 | end | ||
74 | |||
75 | local function add_to_cart (value, name, indent, saved, field) | ||
76 | indent = indent or "" | ||
77 | saved = saved or {} | ||
78 | field = field or name | ||
79 | |||
80 | cart = cart .. indent .. field | ||
81 | |||
82 | if type(value) ~= "table" then | ||
83 | cart = cart .. " = " .. basic_serialize(value) .. ";\n" | ||
84 | else | ||
85 | if saved[value] then | ||
86 | cart = cart .. " = {}; -- " .. saved[value] .. " (self reference)\n" | ||
87 | autoref = autoref .. name .. " = " .. saved[value] .. ";\n" | ||
88 | else | ||
89 | saved[value] = name | ||
90 | --if tablecount(value) == 0 then | ||
91 | if is_empty_table(value) then | ||
92 | cart = cart .. " = {};\n" | ||
93 | else | ||
94 | cart = cart .. " = {\n" | ||
95 | for k, v in pairs(value) do | ||
96 | k = basic_serialize(k) | ||
97 | local fname = ("%s[%s]"):format(name, k) | ||
98 | field = ("[%s]"):format(k) | ||
99 | -- three spaces between levels | ||
100 | add_to_cart(v, fname, indent .. " ", saved, field) | ||
101 | end | ||
102 | cart = cart .. indent .. "};\n" | ||
103 | end | ||
104 | end | ||
105 | end | ||
106 | end | ||
107 | |||
108 | name = name or "__unnamed__" | ||
109 | if type(t) ~= "table" then | ||
110 | return name .. " = " .. basic_serialize(t) | ||
111 | end | ||
112 | cart, autoref = "", "" | ||
113 | add_to_cart(t, name, indent) | ||
114 | return cart .. autoref | ||
115 | end | ||
116 | |||
117 | --- Merges contents of src on top of dst's contents. | ||
118 | -- @param dst Destination table, which will receive src's contents. | ||
119 | -- @param src Table which provides new contents to dst. | ||
120 | -- @see platform_overrides | ||
121 | function util.deep_merge(dst, src) | ||
122 | for k, v in pairs(src) do | ||
123 | if type(v) == "table" then | ||
124 | if not dst[k] then | ||
125 | dst[k] = {} | ||
126 | end | ||
127 | if type(dst[k]) == "table" then | ||
128 | util.deep_merge(dst[k], v) | ||
129 | else | ||
130 | dst[k] = v | ||
131 | end | ||
132 | else | ||
133 | dst[k] = v | ||
134 | end | ||
135 | end | ||
136 | end | ||
137 | |||
138 | --- Remove repeated entries from a path-style string. | ||
139 | -- Example: given ("a;b;c;a;b;d", ";"), returns "a;b;c;d". | ||
140 | -- @param list string: A path string (from $PATH or package.path) | ||
141 | -- @param sep string: The separator | ||
142 | function util.remove_path_dupes(list, sep) | ||
143 | assert(type(list) == "string") | ||
144 | assert(type(sep) == "string") | ||
145 | local parts = util.split_string(list, sep) | ||
146 | local final, entries = {}, {} | ||
147 | for _, part in ipairs(parts) do | ||
148 | part = part:gsub("//", "/") | ||
149 | if not entries[part] then | ||
150 | table.insert(final, part) | ||
151 | entries[part] = true | ||
152 | end | ||
153 | end | ||
154 | return table.concat(final, sep) | ||
155 | end | ||
156 | |||
157 | -- from http://lua-users.org/wiki/SplitJoin | ||
158 | -- by Philippe Lhoste | ||
159 | function util.split_string(str, delim, maxNb) | ||
160 | -- Eliminate bad cases... | ||
161 | if string.find(str, delim) == nil then | ||
162 | return { str } | ||
163 | end | ||
164 | if maxNb == nil or maxNb < 1 then | ||
165 | maxNb = 0 -- No limit | ||
166 | end | ||
167 | local result = {} | ||
168 | local pat = "(.-)" .. delim .. "()" | ||
169 | local nb = 0 | ||
170 | local lastPos | ||
171 | for part, pos in string.gmatch(str, pat) do | ||
172 | nb = nb + 1 | ||
173 | result[nb] = part | ||
174 | lastPos = pos | ||
175 | if nb == maxNb then break end | ||
176 | end | ||
177 | -- Handle the last field | ||
178 | if nb ~= maxNb then | ||
179 | result[nb + 1] = string.sub(str, lastPos) | ||
180 | end | ||
181 | return result | ||
182 | end | ||
183 | |||
184 | --- Return an array of keys of a table. | ||
185 | -- @param tbl table: The input table. | ||
186 | -- @return table: The array of keys. | ||
187 | function util.keys(tbl) | ||
188 | local ks = {} | ||
189 | for k,_ in pairs(tbl) do | ||
190 | table.insert(ks, k) | ||
191 | end | ||
192 | return ks | ||
193 | end | ||
194 | |||
195 | --- Print a line to standard error | ||
196 | function util.printerr(...) | ||
197 | io.stderr:write(table.concat({...},"\t")) | ||
198 | io.stderr:write("\n") | ||
199 | end | ||
200 | |||
201 | --- Simple sort function used as a default for util.sortedpairs. | ||
202 | local function default_sort(a, b) | ||
203 | local ta = type(a) | ||
204 | local tb = type(b) | ||
205 | if ta == "number" and tb == "number" then | ||
206 | return a < b | ||
207 | elseif ta == "number" then | ||
208 | return true | ||
209 | elseif tb == "number" then | ||
210 | return false | ||
211 | else | ||
212 | return tostring(a) < tostring(b) | ||
213 | end | ||
214 | end | ||
215 | |||
216 | --- A table iterator generator that returns elements sorted by key, | ||
217 | -- to be used in "for" loops. | ||
218 | -- @param tbl table: The table to be iterated. | ||
219 | -- @param sort_function function or table or nil: An optional comparison function | ||
220 | -- to be used by table.sort when sorting keys, or an array listing an explicit order | ||
221 | -- for keys. If a value itself is an array, it is taken so that the first element | ||
222 | -- is a string representing the field name, and the second element is a priority table | ||
223 | -- for that key, which is returned by the iterator as the third value after the key | ||
224 | -- and the value. | ||
225 | -- @return function: the iterator function. | ||
226 | function util.sortedpairs(tbl, sort_function) | ||
227 | sort_function = sort_function or default_sort | ||
228 | local keys = util.keys(tbl) | ||
229 | local sub_orders = {} | ||
230 | |||
231 | if type(sort_function) == "function" then | ||
232 | table.sort(keys, sort_function) | ||
233 | else | ||
234 | local order = sort_function | ||
235 | local ordered_keys = {} | ||
236 | local all_keys = keys | ||
237 | keys = {} | ||
238 | |||
239 | for _, order_entry in ipairs(order) do | ||
240 | local key, sub_order | ||
241 | if type(order_entry) == "table" then | ||
242 | key = order_entry[1] | ||
243 | sub_order = order_entry[2] | ||
244 | else | ||
245 | key = order_entry | ||
246 | end | ||
247 | |||
248 | if tbl[key] then | ||
249 | ordered_keys[key] = true | ||
250 | sub_orders[key] = sub_order | ||
251 | table.insert(keys, key) | ||
252 | end | ||
253 | end | ||
254 | |||
255 | table.sort(all_keys, default_sort) | ||
256 | for _, key in ipairs(all_keys) do | ||
257 | if not ordered_keys[key] then | ||
258 | table.insert(keys, key) | ||
259 | end | ||
260 | end | ||
261 | end | ||
262 | |||
263 | local i = 1 | ||
264 | return function() | ||
265 | local key = keys[i] | ||
266 | i = i + 1 | ||
267 | return key, tbl[key], sub_orders[key] | ||
268 | end | ||
269 | end | ||
270 | |||
271 | return util | ||
272 | |||
diff --git a/src/luarocks/core/vers.lua b/src/luarocks/core/vers.lua new file mode 100644 index 00000000..2a765b9b --- /dev/null +++ b/src/luarocks/core/vers.lua | |||
@@ -0,0 +1,191 @@ | |||
1 | |||
2 | local vers = {} | ||
3 | |||
4 | local util = require("luarocks.core.util") | ||
5 | local require = nil | ||
6 | -------------------------------------------------------------------------------- | ||
7 | |||
8 | local deltas = { | ||
9 | scm = 1100, | ||
10 | cvs = 1000, | ||
11 | rc = -1000, | ||
12 | pre = -10000, | ||
13 | beta = -100000, | ||
14 | alpha = -1000000 | ||
15 | } | ||
16 | |||
17 | local version_mt = { | ||
18 | --- Equality comparison for versions. | ||
19 | -- All version numbers must be equal. | ||
20 | -- If both versions have revision numbers, they must be equal; | ||
21 | -- otherwise the revision number is ignored. | ||
22 | -- @param v1 table: version table to compare. | ||
23 | -- @param v2 table: version table to compare. | ||
24 | -- @return boolean: true if they are considered equivalent. | ||
25 | __eq = function(v1, v2) | ||
26 | if #v1 ~= #v2 then | ||
27 | return false | ||
28 | end | ||
29 | for i = 1, #v1 do | ||
30 | if v1[i] ~= v2[i] then | ||
31 | return false | ||
32 | end | ||
33 | end | ||
34 | if v1.revision and v2.revision then | ||
35 | return (v1.revision == v2.revision) | ||
36 | end | ||
37 | return true | ||
38 | end, | ||
39 | --- Size comparison for versions. | ||
40 | -- All version numbers are compared. | ||
41 | -- If both versions have revision numbers, they are compared; | ||
42 | -- otherwise the revision number is ignored. | ||
43 | -- @param v1 table: version table to compare. | ||
44 | -- @param v2 table: version table to compare. | ||
45 | -- @return boolean: true if v1 is considered lower than v2. | ||
46 | __lt = function(v1, v2) | ||
47 | for i = 1, math.max(#v1, #v2) do | ||
48 | local v1i, v2i = v1[i] or 0, v2[i] or 0 | ||
49 | if v1i ~= v2i then | ||
50 | return (v1i < v2i) | ||
51 | end | ||
52 | end | ||
53 | if v1.revision and v2.revision then | ||
54 | return (v1.revision < v2.revision) | ||
55 | end | ||
56 | return false | ||
57 | end | ||
58 | } | ||
59 | |||
60 | local version_cache = {} | ||
61 | setmetatable(version_cache, { | ||
62 | __mode = "kv" | ||
63 | }) | ||
64 | |||
65 | --- Parse a version string, converting to table format. | ||
66 | -- A version table contains all components of the version string | ||
67 | -- converted to numeric format, stored in the array part of the table. | ||
68 | -- If the version contains a revision, it is stored numerically | ||
69 | -- in the 'revision' field. The original string representation of | ||
70 | -- the string is preserved in the 'string' field. | ||
71 | -- Returned version tables use a metatable | ||
72 | -- allowing later comparison through relational operators. | ||
73 | -- @param vstring string: A version number in string format. | ||
74 | -- @return table or nil: A version table or nil | ||
75 | -- if the input string contains invalid characters. | ||
76 | function vers.parse_version(vstring) | ||
77 | if not vstring then return nil end | ||
78 | assert(type(vstring) == "string") | ||
79 | |||
80 | local cached = version_cache[vstring] | ||
81 | if cached then | ||
82 | return cached | ||
83 | end | ||
84 | |||
85 | local version = {} | ||
86 | local i = 1 | ||
87 | |||
88 | local function add_token(number) | ||
89 | version[i] = version[i] and version[i] + number/100000 or number | ||
90 | i = i + 1 | ||
91 | end | ||
92 | |||
93 | -- trim leading and trailing spaces | ||
94 | vstring = vstring:match("^%s*(.*)%s*$") | ||
95 | version.string = vstring | ||
96 | -- store revision separately if any | ||
97 | local main, revision = vstring:match("(.*)%-(%d+)$") | ||
98 | if revision then | ||
99 | vstring = main | ||
100 | version.revision = tonumber(revision) | ||
101 | end | ||
102 | while #vstring > 0 do | ||
103 | -- extract a number | ||
104 | local token, rest = vstring:match("^(%d+)[%.%-%_]*(.*)") | ||
105 | if token then | ||
106 | add_token(tonumber(token)) | ||
107 | else | ||
108 | -- extract a word | ||
109 | token, rest = vstring:match("^(%a+)[%.%-%_]*(.*)") | ||
110 | if not token then | ||
111 | util.printerr("Warning: version number '"..vstring.."' could not be parsed.") | ||
112 | version[i] = 0 | ||
113 | break | ||
114 | end | ||
115 | version[i] = deltas[token] or (token:byte() / 1000) | ||
116 | end | ||
117 | vstring = rest | ||
118 | end | ||
119 | setmetatable(version, version_mt) | ||
120 | version_cache[vstring] = version | ||
121 | return version | ||
122 | end | ||
123 | |||
124 | --- Utility function to compare version numbers given as strings. | ||
125 | -- @param a string: one version. | ||
126 | -- @param b string: another version. | ||
127 | -- @return boolean: True if a > b. | ||
128 | function vers.compare_versions(a, b) | ||
129 | return vers.parse_version(a) > vers.parse_version(b) | ||
130 | end | ||
131 | |||
132 | --- A more lenient check for equivalence between versions. | ||
133 | -- This returns true if the requested components of a version | ||
134 | -- match and ignore the ones that were not given. For example, | ||
135 | -- when requesting "2", then "2", "2.1", "2.3.5-9"... all match. | ||
136 | -- When requesting "2.1", then "2.1", "2.1.3" match, but "2.2" | ||
137 | -- doesn't. | ||
138 | -- @param version string or table: Version to be tested; may be | ||
139 | -- in string format or already parsed into a table. | ||
140 | -- @param requested string or table: Version requested; may be | ||
141 | -- in string format or already parsed into a table. | ||
142 | -- @return boolean: True if the tested version matches the requested | ||
143 | -- version, false otherwise. | ||
144 | local function partial_match(version, requested) | ||
145 | assert(type(version) == "string" or type(version) == "table") | ||
146 | assert(type(requested) == "string" or type(version) == "table") | ||
147 | |||
148 | if type(version) ~= "table" then version = vers.parse_version(version) end | ||
149 | if type(requested) ~= "table" then requested = vers.parse_version(requested) end | ||
150 | if not version or not requested then return false end | ||
151 | |||
152 | for i, ri in ipairs(requested) do | ||
153 | local vi = version[i] or 0 | ||
154 | if ri ~= vi then return false end | ||
155 | end | ||
156 | if requested.revision then | ||
157 | return requested.revision == version.revision | ||
158 | end | ||
159 | return true | ||
160 | end | ||
161 | |||
162 | --- Check if a version satisfies a set of constraints. | ||
163 | -- @param version table: A version in table format | ||
164 | -- @param constraints table: An array of constraints in table format. | ||
165 | -- @return boolean: True if version satisfies all constraints, | ||
166 | -- false otherwise. | ||
167 | function vers.match_constraints(version, constraints) | ||
168 | assert(type(version) == "table") | ||
169 | assert(type(constraints) == "table") | ||
170 | local ok = true | ||
171 | setmetatable(version, version_mt) | ||
172 | for _, constr in pairs(constraints) do | ||
173 | if type(constr.version) == "string" then | ||
174 | constr.version = vers.parse_version(constr.version) | ||
175 | end | ||
176 | local constr_version, constr_op = constr.version, constr.op | ||
177 | setmetatable(constr_version, version_mt) | ||
178 | if constr_op == "==" then ok = version == constr_version | ||
179 | elseif constr_op == "~=" then ok = version ~= constr_version | ||
180 | elseif constr_op == ">" then ok = version > constr_version | ||
181 | elseif constr_op == "<" then ok = version < constr_version | ||
182 | elseif constr_op == ">=" then ok = version >= constr_version | ||
183 | elseif constr_op == "<=" then ok = version <= constr_version | ||
184 | elseif constr_op == "~>" then ok = partial_match(version, constr_version) | ||
185 | end | ||
186 | if not ok then break end | ||
187 | end | ||
188 | return ok | ||
189 | end | ||
190 | |||
191 | return vers | ||
diff --git a/src/luarocks/deps.lua b/src/luarocks/deps.lua index dcebec9b..015e2527 100644 --- a/src/luarocks/deps.lua +++ b/src/luarocks/deps.lua | |||
@@ -1,344 +1,40 @@ | |||
1 | 1 | ||
2 | --- Dependency handling functions. | 2 | --- High-level dependency related functions. |
3 | -- Dependencies are represented in LuaRocks through strings with | ||
4 | -- a package name followed by a comma-separated list of constraints. | ||
5 | -- Each constraint consists of an operator and a version number. | ||
6 | -- In this string format, version numbers are represented as | ||
7 | -- naturally as possible, like they are used by upstream projects | ||
8 | -- (e.g. "2.0beta3"). Internally, LuaRocks converts them to a purely | ||
9 | -- numeric representation, allowing comparison following some | ||
10 | -- "common sense" heuristics. The precise specification of the | ||
11 | -- comparison criteria is the source code of this module, but the | ||
12 | -- test/test_deps.lua file included with LuaRocks provides some | ||
13 | -- insights on what these criteria are. | ||
14 | local deps = {} | 3 | local deps = {} |
15 | package.loaded["luarocks.deps"] = deps | ||
16 | 4 | ||
17 | local cfg = require("luarocks.cfg") | 5 | local cfg = require("luarocks.core.cfg") |
18 | local manif_core = require("luarocks.manif_core") | 6 | local manif = require("luarocks.manif") |
19 | local path = require("luarocks.path") | 7 | local path = require("luarocks.path") |
20 | local dir = require("luarocks.dir") | 8 | local dir = require("luarocks.dir") |
21 | local util = require("luarocks.util") | 9 | local util = require("luarocks.util") |
22 | 10 | local vers = require("luarocks.vers") | |
23 | local operators = { | ||
24 | ["=="] = "==", | ||
25 | ["~="] = "~=", | ||
26 | [">"] = ">", | ||
27 | ["<"] = "<", | ||
28 | [">="] = ">=", | ||
29 | ["<="] = "<=", | ||
30 | ["~>"] = "~>", | ||
31 | -- plus some convenience translations | ||
32 | [""] = "==", | ||
33 | ["="] = "==", | ||
34 | ["!="] = "~=" | ||
35 | } | ||
36 | |||
37 | local deltas = { | ||
38 | scm = 1100, | ||
39 | cvs = 1000, | ||
40 | rc = -1000, | ||
41 | pre = -10000, | ||
42 | beta = -100000, | ||
43 | alpha = -1000000 | ||
44 | } | ||
45 | |||
46 | local version_mt = { | ||
47 | --- Equality comparison for versions. | ||
48 | -- All version numbers must be equal. | ||
49 | -- If both versions have revision numbers, they must be equal; | ||
50 | -- otherwise the revision number is ignored. | ||
51 | -- @param v1 table: version table to compare. | ||
52 | -- @param v2 table: version table to compare. | ||
53 | -- @return boolean: true if they are considered equivalent. | ||
54 | __eq = function(v1, v2) | ||
55 | if #v1 ~= #v2 then | ||
56 | return false | ||
57 | end | ||
58 | for i = 1, #v1 do | ||
59 | if v1[i] ~= v2[i] then | ||
60 | return false | ||
61 | end | ||
62 | end | ||
63 | if v1.revision and v2.revision then | ||
64 | return (v1.revision == v2.revision) | ||
65 | end | ||
66 | return true | ||
67 | end, | ||
68 | --- Size comparison for versions. | ||
69 | -- All version numbers are compared. | ||
70 | -- If both versions have revision numbers, they are compared; | ||
71 | -- otherwise the revision number is ignored. | ||
72 | -- @param v1 table: version table to compare. | ||
73 | -- @param v2 table: version table to compare. | ||
74 | -- @return boolean: true if v1 is considered lower than v2. | ||
75 | __lt = function(v1, v2) | ||
76 | for i = 1, math.max(#v1, #v2) do | ||
77 | local v1i, v2i = v1[i] or 0, v2[i] or 0 | ||
78 | if v1i ~= v2i then | ||
79 | return (v1i < v2i) | ||
80 | end | ||
81 | end | ||
82 | if v1.revision and v2.revision then | ||
83 | return (v1.revision < v2.revision) | ||
84 | end | ||
85 | return false | ||
86 | end | ||
87 | } | ||
88 | |||
89 | local version_cache = {} | ||
90 | setmetatable(version_cache, { | ||
91 | __mode = "kv" | ||
92 | }) | ||
93 | |||
94 | --- Parse a version string, converting to table format. | ||
95 | -- A version table contains all components of the version string | ||
96 | -- converted to numeric format, stored in the array part of the table. | ||
97 | -- If the version contains a revision, it is stored numerically | ||
98 | -- in the 'revision' field. The original string representation of | ||
99 | -- the string is preserved in the 'string' field. | ||
100 | -- Returned version tables use a metatable | ||
101 | -- allowing later comparison through relational operators. | ||
102 | -- @param vstring string: A version number in string format. | ||
103 | -- @return table or nil: A version table or nil | ||
104 | -- if the input string contains invalid characters. | ||
105 | function deps.parse_version(vstring) | ||
106 | if not vstring then return nil end | ||
107 | assert(type(vstring) == "string") | ||
108 | |||
109 | local cached = version_cache[vstring] | ||
110 | if cached then | ||
111 | return cached | ||
112 | end | ||
113 | |||
114 | local version = {} | ||
115 | local i = 1 | ||
116 | |||
117 | local function add_token(number) | ||
118 | version[i] = version[i] and version[i] + number/100000 or number | ||
119 | i = i + 1 | ||
120 | end | ||
121 | |||
122 | -- trim leading and trailing spaces | ||
123 | vstring = vstring:match("^%s*(.*)%s*$") | ||
124 | version.string = vstring | ||
125 | -- store revision separately if any | ||
126 | local main, revision = vstring:match("(.*)%-(%d+)$") | ||
127 | if revision then | ||
128 | vstring = main | ||
129 | version.revision = tonumber(revision) | ||
130 | end | ||
131 | while #vstring > 0 do | ||
132 | -- extract a number | ||
133 | local token, rest = vstring:match("^(%d+)[%.%-%_]*(.*)") | ||
134 | if token then | ||
135 | add_token(tonumber(token)) | ||
136 | else | ||
137 | -- extract a word | ||
138 | token, rest = vstring:match("^(%a+)[%.%-%_]*(.*)") | ||
139 | if not token then | ||
140 | util.printerr("Warning: version number '"..vstring.."' could not be parsed.") | ||
141 | version[i] = 0 | ||
142 | break | ||
143 | end | ||
144 | version[i] = deltas[token] or (token:byte() / 1000) | ||
145 | end | ||
146 | vstring = rest | ||
147 | end | ||
148 | setmetatable(version, version_mt) | ||
149 | version_cache[vstring] = version | ||
150 | return version | ||
151 | end | ||
152 | |||
153 | --- Utility function to compare version numbers given as strings. | ||
154 | -- @param a string: one version. | ||
155 | -- @param b string: another version. | ||
156 | -- @return boolean: True if a > b. | ||
157 | function deps.compare_versions(a, b) | ||
158 | return deps.parse_version(a) > deps.parse_version(b) | ||
159 | end | ||
160 | |||
161 | --- Consumes a constraint from a string, converting it to table format. | ||
162 | -- For example, a string ">= 1.0, > 2.0" is converted to a table in the | ||
163 | -- format {op = ">=", version={1,0}} and the rest, "> 2.0", is returned | ||
164 | -- back to the caller. | ||
165 | -- @param input string: A list of constraints in string format. | ||
166 | -- @return (table, string) or nil: A table representing the same | ||
167 | -- constraints and the string with the unused input, or nil if the | ||
168 | -- input string is invalid. | ||
169 | local function parse_constraint(input) | ||
170 | assert(type(input) == "string") | ||
171 | |||
172 | local no_upgrade, op, version, rest = input:match("^(@?)([<>=~!]*)%s*([%w%.%_%-]+)[%s,]*(.*)") | ||
173 | local _op = operators[op] | ||
174 | version = deps.parse_version(version) | ||
175 | if not _op then | ||
176 | return nil, "Encountered bad constraint operator: '"..tostring(op).."' in '"..input.."'" | ||
177 | end | ||
178 | if not version then | ||
179 | return nil, "Could not parse version from constraint: '"..input.."'" | ||
180 | end | ||
181 | return { op = _op, version = version, no_upgrade = no_upgrade=="@" and true or nil }, rest | ||
182 | end | ||
183 | |||
184 | --- Convert a list of constraints from string to table format. | ||
185 | -- For example, a string ">= 1.0, < 2.0" is converted to a table in the format | ||
186 | -- {{op = ">=", version={1,0}}, {op = "<", version={2,0}}}. | ||
187 | -- Version tables use a metatable allowing later comparison through | ||
188 | -- relational operators. | ||
189 | -- @param input string: A list of constraints in string format. | ||
190 | -- @return table or nil: A table representing the same constraints, | ||
191 | -- or nil if the input string is invalid. | ||
192 | function deps.parse_constraints(input) | ||
193 | assert(type(input) == "string") | ||
194 | |||
195 | local constraints, constraint, oinput = {}, nil, input | ||
196 | while #input > 0 do | ||
197 | constraint, input = parse_constraint(input) | ||
198 | if constraint then | ||
199 | table.insert(constraints, constraint) | ||
200 | else | ||
201 | return nil, "Failed to parse constraint '"..tostring(oinput).."' with error: ".. input | ||
202 | end | ||
203 | end | ||
204 | return constraints | ||
205 | end | ||
206 | |||
207 | --- Convert a dependency from string to table format. | ||
208 | -- For example, a string "foo >= 1.0, < 2.0" | ||
209 | -- is converted to a table in the format | ||
210 | -- {name = "foo", constraints = {{op = ">=", version={1,0}}, | ||
211 | -- {op = "<", version={2,0}}}}. Version tables use a metatable | ||
212 | -- allowing later comparison through relational operators. | ||
213 | -- @param dep string: A dependency in string format | ||
214 | -- as entered in rockspec files. | ||
215 | -- @return table or nil: A table representing the same dependency relation, | ||
216 | -- or nil if the input string is invalid. | ||
217 | function deps.parse_dep(dep) | ||
218 | assert(type(dep) == "string") | ||
219 | |||
220 | local name, rest = dep:match("^%s*([a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*(.*)") | ||
221 | if not name then return nil, "failed to extract dependency name from '"..tostring(dep).."'" end | ||
222 | local constraints, err = deps.parse_constraints(rest) | ||
223 | if not constraints then return nil, err end | ||
224 | return { name = name, constraints = constraints } | ||
225 | end | ||
226 | |||
227 | --- Convert a version table to a string. | ||
228 | -- @param v table: The version table | ||
229 | -- @param internal boolean or nil: Whether to display versions in their | ||
230 | -- internal representation format or how they were specified. | ||
231 | -- @return string: The dependency information pretty-printed as a string. | ||
232 | function deps.show_version(v, internal) | ||
233 | assert(type(v) == "table") | ||
234 | assert(type(internal) == "boolean" or not internal) | ||
235 | |||
236 | return (internal | ||
237 | and table.concat(v, ":")..(v.revision and tostring(v.revision) or "") | ||
238 | or v.string) | ||
239 | end | ||
240 | |||
241 | --- Convert a dependency in table format to a string. | ||
242 | -- @param dep table: The dependency in table format | ||
243 | -- @param internal boolean or nil: Whether to display versions in their | ||
244 | -- internal representation format or how they were specified. | ||
245 | -- @return string: The dependency information pretty-printed as a string. | ||
246 | function deps.show_dep(dep, internal) | ||
247 | assert(type(dep) == "table") | ||
248 | assert(type(internal) == "boolean" or not internal) | ||
249 | |||
250 | if #dep.constraints > 0 then | ||
251 | local pretty = {} | ||
252 | for _, c in ipairs(dep.constraints) do | ||
253 | table.insert(pretty, c.op .. " " .. deps.show_version(c.version, internal)) | ||
254 | end | ||
255 | return dep.name.." "..table.concat(pretty, ", ") | ||
256 | else | ||
257 | return dep.name | ||
258 | end | ||
259 | end | ||
260 | |||
261 | --- A more lenient check for equivalence between versions. | ||
262 | -- This returns true if the requested components of a version | ||
263 | -- match and ignore the ones that were not given. For example, | ||
264 | -- when requesting "2", then "2", "2.1", "2.3.5-9"... all match. | ||
265 | -- When requesting "2.1", then "2.1", "2.1.3" match, but "2.2" | ||
266 | -- doesn't. | ||
267 | -- @param version string or table: Version to be tested; may be | ||
268 | -- in string format or already parsed into a table. | ||
269 | -- @param requested string or table: Version requested; may be | ||
270 | -- in string format or already parsed into a table. | ||
271 | -- @return boolean: True if the tested version matches the requested | ||
272 | -- version, false otherwise. | ||
273 | local function partial_match(version, requested) | ||
274 | assert(type(version) == "string" or type(version) == "table") | ||
275 | assert(type(requested) == "string" or type(version) == "table") | ||
276 | |||
277 | if type(version) ~= "table" then version = deps.parse_version(version) end | ||
278 | if type(requested) ~= "table" then requested = deps.parse_version(requested) end | ||
279 | if not version or not requested then return false end | ||
280 | |||
281 | for i, ri in ipairs(requested) do | ||
282 | local vi = version[i] or 0 | ||
283 | if ri ~= vi then return false end | ||
284 | end | ||
285 | if requested.revision then | ||
286 | return requested.revision == version.revision | ||
287 | end | ||
288 | return true | ||
289 | end | ||
290 | |||
291 | --- Check if a version satisfies a set of constraints. | ||
292 | -- @param version table: A version in table format | ||
293 | -- @param constraints table: An array of constraints in table format. | ||
294 | -- @return boolean: True if version satisfies all constraints, | ||
295 | -- false otherwise. | ||
296 | function deps.match_constraints(version, constraints) | ||
297 | assert(type(version) == "table") | ||
298 | assert(type(constraints) == "table") | ||
299 | local ok = true | ||
300 | setmetatable(version, version_mt) | ||
301 | for _, constr in pairs(constraints) do | ||
302 | if type(constr.version) == "string" then | ||
303 | constr.version = deps.parse_version(constr.version) | ||
304 | end | ||
305 | local constr_version, constr_op = constr.version, constr.op | ||
306 | setmetatable(constr_version, version_mt) | ||
307 | if constr_op == "==" then ok = version == constr_version | ||
308 | elseif constr_op == "~=" then ok = version ~= constr_version | ||
309 | elseif constr_op == ">" then ok = version > constr_version | ||
310 | elseif constr_op == "<" then ok = version < constr_version | ||
311 | elseif constr_op == ">=" then ok = version >= constr_version | ||
312 | elseif constr_op == "<=" then ok = version <= constr_version | ||
313 | elseif constr_op == "~>" then ok = partial_match(version, constr_version) | ||
314 | end | ||
315 | if not ok then break end | ||
316 | end | ||
317 | return ok | ||
318 | end | ||
319 | 11 | ||
320 | --- Attempt to match a dependency to an installed rock. | 12 | --- Attempt to match a dependency to an installed rock. |
321 | -- @param dep table: A dependency parsed in table format. | 13 | -- @param dep table: A dependency parsed in table format. |
322 | -- @param blacklist table: Versions that can't be accepted. Table where keys | 14 | -- @param blacklist table: Versions that can't be accepted. Table where keys |
323 | -- are program versions and values are 'true'. | 15 | -- are program versions and values are 'true'. |
16 | -- @param rocks_provided table: A table of auto-dependencies provided | ||
17 | -- by this Lua implementation for the given dependency. | ||
324 | -- @return string or nil: latest installed version of the rock matching the dependency | 18 | -- @return string or nil: latest installed version of the rock matching the dependency |
325 | -- or nil if it could not be matched. | 19 | -- or nil if it could not be matched. |
326 | local function match_dep(dep, blacklist, deps_mode) | 20 | local function match_dep(dep, blacklist, deps_mode, rocks_provided) |
327 | assert(type(dep) == "table") | 21 | assert(type(dep) == "table") |
328 | 22 | assert(type(rocks_provided) == "table") | |
23 | |||
329 | local versions | 24 | local versions |
330 | if cfg.rocks_provided[dep.name] then | 25 | local provided = rocks_provided[dep.name] |
331 | -- provided rocks have higher priority than manifest's rocks | 26 | if provided then |
332 | versions = { cfg.rocks_provided[dep.name] } | 27 | -- Provided rocks have higher priority than manifest's rocks. |
28 | versions = { provided } | ||
333 | else | 29 | else |
334 | versions = manif_core.get_versions(dep.name, deps_mode) | 30 | versions = manif.get_versions(dep.name, deps_mode) |
335 | end | 31 | end |
336 | 32 | ||
337 | local latest_version | 33 | local latest_version |
338 | for _, vstring in ipairs(versions) do | 34 | for _, vstring in ipairs(versions) do |
339 | if not blacklist or not blacklist[vstring] then | 35 | if not blacklist or not blacklist[vstring] then |
340 | local version = deps.parse_version(vstring) | 36 | local version = vers.parse_version(vstring) |
341 | if deps.match_constraints(version, dep.constraints) then | 37 | if vers.match_constraints(version, dep.constraints) then |
342 | if not latest_version or version > latest_version then | 38 | if not latest_version or version > latest_version then |
343 | latest_version = version | 39 | latest_version = version |
344 | end | 40 | end |
@@ -366,9 +62,9 @@ function deps.match_deps(rockspec, blacklist, deps_mode) | |||
366 | local matched, missing, no_upgrade = {}, {}, {} | 62 | local matched, missing, no_upgrade = {}, {}, {} |
367 | 63 | ||
368 | for _, dep in ipairs(rockspec.dependencies) do | 64 | for _, dep in ipairs(rockspec.dependencies) do |
369 | local found = match_dep(dep, blacklist and blacklist[dep.name] or nil, deps_mode) | 65 | local found = match_dep(dep, blacklist and blacklist[dep.name] or nil, deps_mode, rockspec.rocks_provided) |
370 | if found then | 66 | if found then |
371 | if not cfg.rocks_provided[dep.name] then | 67 | if not rockspec.rocks_provided[dep.name] then |
372 | matched[dep] = {name = dep.name, version = found} | 68 | matched[dep] = {name = dep.name, version = found} |
373 | end | 69 | end |
374 | else | 70 | else |
@@ -393,10 +89,10 @@ local function values_set(tbl) | |||
393 | return set | 89 | return set |
394 | end | 90 | end |
395 | 91 | ||
396 | local function rock_status(name, deps_mode) | 92 | local function rock_status(name, deps_mode, rocks_provided) |
397 | local search = require("luarocks.search") | 93 | local search = require("luarocks.search") |
398 | local installed = match_dep(search.make_query(name), nil, deps_mode) | 94 | local installed = match_dep(search.make_query(name), nil, deps_mode, rocks_provided) |
399 | local installation_type = cfg.rocks_provided[name] and "provided by VM" or "installed" | 95 | local installation_type = rocks_provided[name] and "provided by VM" or "installed" |
400 | return installed and installed.." "..installation_type or "not installed" | 96 | return installed and installed.." "..installation_type or "not installed" |
401 | end | 97 | end |
402 | 98 | ||
@@ -405,19 +101,21 @@ end | |||
405 | -- @param version string: package version. | 101 | -- @param version string: package version. |
406 | -- @param dependencies table: array of dependencies. | 102 | -- @param dependencies table: array of dependencies. |
407 | -- @param deps_mode string: Which trees to check dependencies for: | 103 | -- @param deps_mode string: Which trees to check dependencies for: |
104 | -- @param rocks_provided table: A table of auto-dependencies provided | ||
105 | -- by this Lua implementation for the given dependency. | ||
408 | -- "one" for the current default tree, "all" for all trees, | 106 | -- "one" for the current default tree, "all" for all trees, |
409 | -- "order" for all trees with priority >= the current default, "none" for no trees. | 107 | -- "order" for all trees with priority >= the current default, "none" for no trees. |
410 | function deps.report_missing_dependencies(name, version, dependencies, deps_mode) | 108 | function deps.report_missing_dependencies(name, version, dependencies, deps_mode, rocks_provided) |
411 | local first_missing_dep = true | 109 | local first_missing_dep = true |
412 | 110 | ||
413 | for _, dep in ipairs(dependencies) do | 111 | for _, dep in ipairs(dependencies) do |
414 | if not match_dep(dep, nil, deps_mode) then | 112 | if not match_dep(dep, nil, deps_mode, rocks_provided) then |
415 | if first_missing_dep then | 113 | if first_missing_dep then |
416 | util.printout(("Missing dependencies for %s %s:"):format(name, version)) | 114 | util.printout(("Missing dependencies for %s %s:"):format(name, version)) |
417 | first_missing_dep = false | 115 | first_missing_dep = false |
418 | end | 116 | end |
419 | 117 | ||
420 | util.printout((" %s (%s)"):format(deps.show_dep(dep), rock_status(dep.name, deps_mode))) | 118 | util.printout((" %s (%s)"):format(vers.show_dep(dep), rock_status(dep.name, deps_mode, rocks_provided))) |
421 | end | 119 | end |
422 | end | 120 | end |
423 | end | 121 | end |
@@ -432,7 +130,7 @@ end | |||
432 | function deps.fulfill_dependencies(rockspec, deps_mode) | 130 | function deps.fulfill_dependencies(rockspec, deps_mode) |
433 | 131 | ||
434 | local search = require("luarocks.search") | 132 | local search = require("luarocks.search") |
435 | local install = require("luarocks.install") | 133 | local install = require("luarocks.cmd.install") |
436 | 134 | ||
437 | if rockspec.supported_platforms then | 135 | if rockspec.supported_platforms then |
438 | if not deps.platforms_set then | 136 | if not deps.platforms_set then |
@@ -440,7 +138,8 @@ function deps.fulfill_dependencies(rockspec, deps_mode) | |||
440 | end | 138 | end |
441 | local supported = nil | 139 | local supported = nil |
442 | for _, plat in pairs(rockspec.supported_platforms) do | 140 | for _, plat in pairs(rockspec.supported_platforms) do |
443 | local neg, plat = plat:match("^(!?)(.*)") | 141 | local neg |
142 | neg, plat = plat:match("^(!?)(.*)") | ||
444 | if neg == "!" then | 143 | if neg == "!" then |
445 | if deps.platforms_set[plat] then | 144 | if deps.platforms_set[plat] then |
446 | return nil, "This rockspec for "..rockspec.package.." does not support "..plat.." platforms." | 145 | return nil, "This rockspec for "..rockspec.package.." does not support "..plat.." platforms." |
@@ -461,23 +160,23 @@ function deps.fulfill_dependencies(rockspec, deps_mode) | |||
461 | end | 160 | end |
462 | end | 161 | end |
463 | 162 | ||
464 | deps.report_missing_dependencies(rockspec.name, rockspec.version, rockspec.dependencies, deps_mode) | 163 | deps.report_missing_dependencies(rockspec.name, rockspec.version, rockspec.dependencies, deps_mode, rockspec.rocks_provided) |
465 | 164 | ||
466 | local first_missing_dep = true | 165 | local first_missing_dep = true |
467 | 166 | ||
468 | for _, dep in ipairs(rockspec.dependencies) do | 167 | for _, dep in ipairs(rockspec.dependencies) do |
469 | if not match_dep(dep, nil, deps_mode) then | 168 | if not match_dep(dep, nil, deps_mode, rockspec.rocks_provided) then |
470 | if first_missing_dep then | 169 | if first_missing_dep then |
471 | util.printout() | 170 | util.printout() |
472 | first_missing_dep = false | 171 | first_missing_dep = false |
473 | end | 172 | end |
474 | 173 | ||
475 | util.printout(("%s %s depends on %s (%s)"):format( | 174 | util.printout(("%s %s depends on %s (%s)"):format( |
476 | rockspec.name, rockspec.version, deps.show_dep(dep), rock_status(dep.name, deps_mode))) | 175 | rockspec.name, rockspec.version, vers.show_dep(dep), rock_status(dep.name, deps_mode, rockspec.rocks_provided))) |
477 | 176 | ||
478 | if dep.constraints[1] and dep.constraints[1].no_upgrade then | 177 | if dep.constraints[1] and dep.constraints[1].no_upgrade then |
479 | util.printerr("This version of "..rockspec.name.." is designed for use with") | 178 | util.printerr("This version of "..rockspec.name.." is designed for use with") |
480 | util.printerr(deps.show_dep(dep)..", but is configured to avoid upgrading it") | 179 | util.printerr(vers.show_dep(dep)..", but is configured to avoid upgrading it") |
481 | util.printerr("automatically. Please upgrade "..dep.name.." with") | 180 | util.printerr("automatically. Please upgrade "..dep.name.." with") |
482 | util.printerr(" luarocks install "..dep.name) | 181 | util.printerr(" luarocks install "..dep.name) |
483 | util.printerr("or choose an older version of "..rockspec.name.." with") | 182 | util.printerr("or choose an older version of "..rockspec.name.." with") |
@@ -487,7 +186,7 @@ function deps.fulfill_dependencies(rockspec, deps_mode) | |||
487 | 186 | ||
488 | local url, search_err = search.find_suitable_rock(dep) | 187 | local url, search_err = search.find_suitable_rock(dep) |
489 | if not url then | 188 | if not url then |
490 | return nil, "Could not satisfy dependency "..deps.show_dep(dep)..": "..search_err | 189 | return nil, "Could not satisfy dependency "..vers.show_dep(dep)..": "..search_err |
491 | end | 190 | end |
492 | util.printout("Installing "..url) | 191 | util.printout("Installing "..url) |
493 | local ok, install_err, errcode = install.command({deps_mode = deps_mode}, url) | 192 | local ok, install_err, errcode = install.command({deps_mode = deps_mode}, url) |
@@ -717,7 +416,10 @@ function deps.scan_deps(results, manifest, name, version, deps_mode) | |||
717 | end | 416 | end |
718 | dependencies_name[version] = rockspec.dependencies | 417 | dependencies_name[version] = rockspec.dependencies |
719 | else | 418 | else |
720 | rockspec = { dependencies = deplist } | 419 | rockspec = { |
420 | dependencies = deplist, | ||
421 | rocks_provided = setmetatable({}, { __index = cfg.rocks_provided_3_0 }) | ||
422 | } | ||
721 | end | 423 | end |
722 | local matched = deps.match_deps(rockspec, nil, deps_mode) | 424 | local matched = deps.match_deps(rockspec, nil, deps_mode) |
723 | results[name] = version | 425 | results[name] = version |
@@ -745,8 +447,4 @@ function deps.get_deps_mode(flags) | |||
745 | end | 447 | end |
746 | end | 448 | end |
747 | 449 | ||
748 | function deps.deps_mode_to_flag(deps_mode) | ||
749 | return "--deps-mode="..deps_mode | ||
750 | end | ||
751 | |||
752 | return deps | 450 | return deps |
diff --git a/src/luarocks/dir.lua b/src/luarocks/dir.lua index f72ebd6c..71477804 100644 --- a/src/luarocks/dir.lua +++ b/src/luarocks/dir.lua | |||
@@ -1,9 +1,7 @@ | |||
1 | 1 | ||
2 | --- Generic utilities for handling pathnames. | 2 | --- Generic utilities for handling pathnames. |
3 | local dir = {} | 3 | local dir = {} |
4 | package.loaded["luarocks.dir"] = dir | 4 | setmetatable(dir, { __index = require("luarocks.core.dir") }) |
5 | |||
6 | dir.separator = "/" | ||
7 | 5 | ||
8 | --- Strip the path off a path+filename. | 6 | --- Strip the path off a path+filename. |
9 | -- @param pathname string: A path+name, such as "/a/b/c" | 7 | -- @param pathname string: A path+name, such as "/a/b/c" |
@@ -26,39 +24,6 @@ function dir.dir_name(pathname) | |||
26 | return (pathname:gsub("/*$", ""):match("(.*)[/]+[^/]*")) or "" | 24 | return (pathname:gsub("/*$", ""):match("(.*)[/]+[^/]*")) or "" |
27 | end | 25 | end |
28 | 26 | ||
29 | --- Describe a path in a cross-platform way. | ||
30 | -- Use this function to avoid platform-specific directory | ||
31 | -- separators in other modules. Removes trailing slashes from | ||
32 | -- each component given, to avoid repeated separators. | ||
33 | -- Separators inside strings are kept, to handle URLs containing | ||
34 | -- protocols. | ||
35 | -- @param ... strings representing directories | ||
36 | -- @return string: a string with a platform-specific representation | ||
37 | -- of the path. | ||
38 | function dir.path(...) | ||
39 | local t = {...} | ||
40 | while t[1] == "" do | ||
41 | table.remove(t, 1) | ||
42 | end | ||
43 | return (table.concat(t, "/"):gsub("([^:])/+", "%1/"):gsub("^/+", "/"):gsub("/*$", "")) | ||
44 | end | ||
45 | |||
46 | --- Split protocol and path from an URL or local pathname. | ||
47 | -- URLs should be in the "protocol://path" format. | ||
48 | -- For local pathnames, "file" is returned as the protocol. | ||
49 | -- @param url string: an URL or a local pathname. | ||
50 | -- @return string, string: the protocol, and the pathname without the protocol. | ||
51 | function dir.split_url(url) | ||
52 | assert(type(url) == "string") | ||
53 | |||
54 | local protocol, pathname = url:match("^([^:]*)://(.*)") | ||
55 | if not protocol then | ||
56 | protocol = "file" | ||
57 | pathname = url | ||
58 | end | ||
59 | return protocol, pathname | ||
60 | end | ||
61 | |||
62 | --- Normalize a url or local path. | 27 | --- Normalize a url or local path. |
63 | -- URLs should be in the "protocol://path" format. System independent | 28 | -- URLs should be in the "protocol://path" format. System independent |
64 | -- forward slashes are used, removing trailing and double slashes | 29 | -- forward slashes are used, removing trailing and double slashes |
diff --git a/src/luarocks/download.lua b/src/luarocks/download.lua index e434cdbb..ec9996b2 100644 --- a/src/luarocks/download.lua +++ b/src/luarocks/download.lua | |||
@@ -1,27 +1,11 @@ | |||
1 | |||
2 | --- Module implementing the luarocks "download" command. | ||
3 | -- Download a rock from the repository. | ||
4 | local download = {} | 1 | local download = {} |
5 | package.loaded["luarocks.download"] = download | ||
6 | 2 | ||
7 | local util = require("luarocks.util") | ||
8 | local path = require("luarocks.path") | 3 | local path = require("luarocks.path") |
9 | local fetch = require("luarocks.fetch") | 4 | local fetch = require("luarocks.fetch") |
10 | local search = require("luarocks.search") | 5 | local search = require("luarocks.search") |
11 | local fs = require("luarocks.fs") | 6 | local fs = require("luarocks.fs") |
12 | local dir = require("luarocks.dir") | 7 | local dir = require("luarocks.dir") |
13 | local cfg = require("luarocks.cfg") | 8 | local cfg = require("luarocks.core.cfg") |
14 | |||
15 | util.add_run_function(download) | ||
16 | download.help_summary = "Download a specific rock file from a rocks server." | ||
17 | download.help_arguments = "[--all] [--arch=<arch> | --source | --rockspec] [<name> [<version>]]" | ||
18 | |||
19 | download.help = [[ | ||
20 | --all Download all files if there are multiple matches. | ||
21 | --source Download .src.rock if available. | ||
22 | --rockspec Download .rockspec if available. | ||
23 | --arch=<arch> Download rock for a specific architecture. | ||
24 | ]] | ||
25 | 9 | ||
26 | local function get_file(filename) | 10 | local function get_file(filename) |
27 | local protocol, pathname = dir.split_url(filename) | 11 | local protocol, pathname = dir.split_url(filename) |
@@ -79,31 +63,4 @@ function download.download(arch, name, version, all) | |||
79 | (search_err and ": "..search_err or ".") | 63 | (search_err and ": "..search_err or ".") |
80 | end | 64 | end |
81 | 65 | ||
82 | --- Driver function for the "download" command. | ||
83 | -- @param name string: a rock name. | ||
84 | -- @param version string or nil: if the name of a package is given, a | ||
85 | -- version may also be passed. | ||
86 | -- @return boolean or (nil, string): true if successful or nil followed | ||
87 | -- by an error message. | ||
88 | function download.command(flags, name, version) | ||
89 | assert(type(version) == "string" or not version) | ||
90 | if type(name) ~= "string" and not flags["all"] then | ||
91 | return nil, "Argument missing. "..util.see_help("download") | ||
92 | end | ||
93 | if not name then name, version = "", "" end | ||
94 | |||
95 | local arch | ||
96 | |||
97 | if flags["source"] then | ||
98 | arch = "src" | ||
99 | elseif flags["rockspec"] then | ||
100 | arch = "rockspec" | ||
101 | elseif flags["arch"] then | ||
102 | arch = flags["arch"] | ||
103 | end | ||
104 | |||
105 | local dl, err = download.download(arch, name:lower(), version, flags["all"]) | ||
106 | return dl and true, err | ||
107 | end | ||
108 | |||
109 | return download | 66 | return download |
diff --git a/src/luarocks/fetch.lua b/src/luarocks/fetch.lua index 76f366cd..2cad3df2 100644 --- a/src/luarocks/fetch.lua +++ b/src/luarocks/fetch.lua | |||
@@ -1,16 +1,15 @@ | |||
1 | 1 | ||
2 | --- Functions related to fetching and loading local and remote files. | 2 | --- Functions related to fetching and loading local and remote files. |
3 | local fetch = {} | 3 | local fetch = {} |
4 | package.loaded["luarocks.fetch"] = fetch | ||
5 | 4 | ||
6 | local fs = require("luarocks.fs") | 5 | local fs = require("luarocks.fs") |
7 | local dir = require("luarocks.dir") | 6 | local dir = require("luarocks.dir") |
8 | local type_check = require("luarocks.type_check") | 7 | local type_check = require("luarocks.type_check") |
9 | local path = require("luarocks.path") | 8 | local path = require("luarocks.path") |
10 | local deps = require("luarocks.deps") | 9 | local vers = require("luarocks.vers") |
11 | local persist = require("luarocks.persist") | 10 | local persist = require("luarocks.persist") |
12 | local util = require("luarocks.util") | 11 | local util = require("luarocks.util") |
13 | local cfg = require("luarocks.cfg") | 12 | local cfg = require("luarocks.core.cfg") |
14 | 13 | ||
15 | function fetch.is_basic_protocol(protocol, remote) | 14 | function fetch.is_basic_protocol(protocol, remote) |
16 | return protocol == "http" or protocol == "https" or protocol == "ftp" or (not remote and protocol == "file") | 15 | return protocol == "http" or protocol == "https" or protocol == "ftp" or (not remote and protocol == "file") |
@@ -198,7 +197,7 @@ function fetch.load_local_rockspec(filename, quick) | |||
198 | local globals = err | 197 | local globals = err |
199 | 198 | ||
200 | if rockspec.rockspec_format then | 199 | if rockspec.rockspec_format then |
201 | if deps.compare_versions(rockspec.rockspec_format, type_check.rockspec_format) then | 200 | if vers.compare_versions(rockspec.rockspec_format, type_check.rockspec_format) then |
202 | return nil, "Rockspec format "..rockspec.rockspec_format.." is not supported, please upgrade LuaRocks." | 201 | return nil, "Rockspec format "..rockspec.rockspec_format.." is not supported, please upgrade LuaRocks." |
203 | end | 202 | end |
204 | end | 203 | end |
@@ -209,6 +208,8 @@ function fetch.load_local_rockspec(filename, quick) | |||
209 | return nil, filename..": "..err | 208 | return nil, filename..": "..err |
210 | end | 209 | end |
211 | end | 210 | end |
211 | |||
212 | rockspec.format_is_at_least = vers.format_is_at_least | ||
212 | 213 | ||
213 | util.platform_overrides(rockspec.build) | 214 | util.platform_overrides(rockspec.build) |
214 | util.platform_overrides(rockspec.dependencies) | 215 | util.platform_overrides(rockspec.dependencies) |
@@ -244,13 +245,22 @@ function fetch.load_local_rockspec(filename, quick) | |||
244 | rockspec.local_filename = filename | 245 | rockspec.local_filename = filename |
245 | local filebase = rockspec.source.file or rockspec.source.url | 246 | local filebase = rockspec.source.file or rockspec.source.url |
246 | local base = fetch.url_to_base_dir(filebase) | 247 | local base = fetch.url_to_base_dir(filebase) |
248 | rockspec.source.dir_set = rockspec.source.dir ~= nil | ||
247 | rockspec.source.dir = rockspec.source.dir | 249 | rockspec.source.dir = rockspec.source.dir |
248 | or rockspec.source.module | 250 | or rockspec.source.module |
249 | or ((filebase:match("%.lua$") or filebase:match("%.c$")) and ".") | 251 | or ( (filebase:match("%.lua$") or filebase:match("%.c$")) |
252 | and (rockspec:format_is_at_least("3.0") | ||
253 | and (fetch.is_basic_protocol(protocol) and "." or base) | ||
254 | or ".") ) | ||
250 | or base | 255 | or base |
256 | |||
257 | rockspec.rocks_provided = (rockspec:format_is_at_least("3.0") | ||
258 | and cfg.rocks_provided_3_0 | ||
259 | or cfg.rocks_provided) | ||
260 | |||
251 | if rockspec.dependencies then | 261 | if rockspec.dependencies then |
252 | for i = 1, #rockspec.dependencies do | 262 | for i = 1, #rockspec.dependencies do |
253 | local parsed, err = deps.parse_dep(rockspec.dependencies[i]) | 263 | local parsed, err = vers.parse_dep(rockspec.dependencies[i]) |
254 | if not parsed then | 264 | if not parsed then |
255 | return nil, "Parse error processing dependency '"..rockspec.dependencies[i].."': "..tostring(err) | 265 | return nil, "Parse error processing dependency '"..rockspec.dependencies[i].."': "..tostring(err) |
256 | end | 266 | end |
@@ -347,7 +357,29 @@ function fetch.get_sources(rockspec, extract, dest_dir) | |||
347 | ok, err = fs.unpack_archive(rockspec.source.file) | 357 | ok, err = fs.unpack_archive(rockspec.source.file) |
348 | if not ok then return nil, err end | 358 | if not ok then return nil, err end |
349 | if not fs.exists(rockspec.source.dir) then | 359 | if not fs.exists(rockspec.source.dir) then |
350 | return nil, "Directory "..rockspec.source.dir.." not found inside archive "..rockspec.source.file, "source.dir", source_file, store_dir | 360 | |
361 | -- If rockspec.source.dir can't be found, see if we only have one | ||
362 | -- directory in store_dir. If that's the case, assume it's what | ||
363 | -- we're looking for. | ||
364 | -- We only do this if the rockspec source.dir was not set, and only | ||
365 | -- with rockspecs newer than 3.0. | ||
366 | local dir_count, found_dir = 0 | ||
367 | |||
368 | if not rockspec.source.dir_set and rockspec:format_is_at_least("3.0") then | ||
369 | local files = fs.list_dir() | ||
370 | for _, f in ipairs(files) do | ||
371 | if fs.is_dir(f) then | ||
372 | dir_count = dir_count + 1 | ||
373 | found_dir = f | ||
374 | end | ||
375 | end | ||
376 | end | ||
377 | |||
378 | if dir_count == 1 then | ||
379 | rockspec.source.dir = found_dir | ||
380 | else | ||
381 | return nil, "Directory "..rockspec.source.dir.." not found inside archive "..rockspec.source.file, "source.dir", source_file, store_dir | ||
382 | end | ||
351 | end | 383 | end |
352 | fs.pop_dir() | 384 | fs.pop_dir() |
353 | end | 385 | end |
diff --git a/src/luarocks/fetch/git.lua b/src/luarocks/fetch/git.lua index f61d89e9..edc11762 100644 --- a/src/luarocks/fetch/git.lua +++ b/src/luarocks/fetch/git.lua | |||
@@ -6,20 +6,48 @@ local unpack = unpack or table.unpack | |||
6 | 6 | ||
7 | local fs = require("luarocks.fs") | 7 | local fs = require("luarocks.fs") |
8 | local dir = require("luarocks.dir") | 8 | local dir = require("luarocks.dir") |
9 | local vers = require("luarocks.vers") | ||
9 | local util = require("luarocks.util") | 10 | local util = require("luarocks.util") |
10 | 11 | ||
12 | local cached_git_version | ||
13 | |||
14 | --- Get git version. | ||
15 | -- @param git_cmd string: name of git command. | ||
16 | -- @return table: git version as returned by luarocks.vers.parse_version. | ||
17 | local function git_version(git_cmd) | ||
18 | if not cached_git_version then | ||
19 | local version_line = io.popen(fs.Q(git_cmd)..' --version'):read() | ||
20 | local version_string = version_line:match('%d-%.%d+%.?%d*') | ||
21 | cached_git_version = vers.parse_version(version_string) | ||
22 | end | ||
23 | |||
24 | return cached_git_version | ||
25 | end | ||
26 | |||
27 | --- Check if git satisfies version requirement. | ||
28 | -- @param git_cmd string: name of git command. | ||
29 | -- @param version string: required version. | ||
30 | -- @return boolean: true if git matches version or is newer, false otherwise. | ||
31 | local function git_is_at_least(git_cmd, version) | ||
32 | return git_version(git_cmd) >= vers.parse_version(version) | ||
33 | end | ||
34 | |||
11 | --- Git >= 1.7.10 can clone a branch **or tag**, < 1.7.10 by branch only. We | 35 | --- Git >= 1.7.10 can clone a branch **or tag**, < 1.7.10 by branch only. We |
12 | -- need to know this in order to build the appropriate command; if we can't | 36 | -- need to know this in order to build the appropriate command; if we can't |
13 | -- clone by tag then we'll have to issue a subsequent command to check out the | 37 | -- clone by tag then we'll have to issue a subsequent command to check out the |
14 | -- given tag. | 38 | -- given tag. |
39 | -- @param git_cmd string: name of git command. | ||
15 | -- @return boolean: Whether Git can clone by tag. | 40 | -- @return boolean: Whether Git can clone by tag. |
16 | local function git_can_clone_by_tag(git_cmd) | 41 | local function git_can_clone_by_tag(git_cmd) |
17 | local version_string = io.popen(fs.Q(git_cmd)..' --version'):read() | 42 | return git_is_at_least(git_cmd, "1.7.10") |
18 | local major, minor, tiny = version_string:match('(%d-)%.(%d+)%.?(%d*)') | 43 | end |
19 | major, minor, tiny = tonumber(major), tonumber(minor), tonumber(tiny) or 0 | 44 | |
20 | local value = major > 1 or (major == 1 and (minor > 7 or (minor == 7 and tiny >= 10))) | 45 | --- Git >= 1.8.4 can fetch submodules shallowly, saving bandwidth and time for |
21 | git_can_clone_by_tag = function() return value end | 46 | -- submodules with large history. |
22 | return value | 47 | -- @param git_cmd string: name of git command. |
48 | -- @return boolean: Whether Git can fetch submodules shallowly. | ||
49 | local function git_supports_shallow_submodules(git_cmd) | ||
50 | return git_is_at_least(git_cmd, "1.8.4") | ||
23 | end | 51 | end |
24 | 52 | ||
25 | --- Download sources for building a rock, using git. | 53 | --- Download sources for building a rock, using git. |
@@ -76,12 +104,25 @@ function git.get_sources(rockspec, extract, dest_dir, depth) | |||
76 | ok, err = fs.change_dir(module) | 104 | ok, err = fs.change_dir(module) |
77 | if not ok then return nil, err end | 105 | if not ok then return nil, err end |
78 | if tag_or_branch and not git_can_clone_by_tag() then | 106 | if tag_or_branch and not git_can_clone_by_tag() then |
79 | local checkout_command = {fs.Q(git_cmd), "checkout", tag_or_branch} | 107 | if not fs.execute(fs.Q(git_cmd), "checkout", tag_or_branch) then |
80 | if not fs.execute(unpack(checkout_command)) then | ||
81 | return nil, 'Failed to check out the "' .. tag_or_branch ..'" tag or branch.' | 108 | return nil, 'Failed to check out the "' .. tag_or_branch ..'" tag or branch.' |
82 | end | 109 | end |
83 | end | 110 | end |
84 | 111 | ||
112 | -- Fetching git submodules is supported only when rockspec format is >= 3.0. | ||
113 | if rockspec:format_is_at_least("3.0") then | ||
114 | command = {fs.Q(git_cmd), "submodule", "update", "--init", "--recursive"} | ||
115 | |||
116 | if git_supports_shallow_submodules(git_cmd) then | ||
117 | -- Fetch only the last commit of each submodule. | ||
118 | table.insert(command, 5, "--depth=1") | ||
119 | end | ||
120 | |||
121 | if not fs.execute(unpack(command)) then | ||
122 | return nil, 'Failed to fetch submodules.' | ||
123 | end | ||
124 | end | ||
125 | |||
85 | fs.delete(dir.path(store_dir, module, ".git")) | 126 | fs.delete(dir.path(store_dir, module, ".git")) |
86 | fs.delete(dir.path(store_dir, module, ".gitignore")) | 127 | fs.delete(dir.path(store_dir, module, ".gitignore")) |
87 | fs.pop_dir() | 128 | fs.pop_dir() |
diff --git a/src/luarocks/fs.lua b/src/luarocks/fs.lua index 54cc7d73..7322e552 100644 --- a/src/luarocks/fs.lua +++ b/src/luarocks/fs.lua | |||
@@ -8,9 +8,10 @@ | |||
8 | local pairs = pairs | 8 | local pairs = pairs |
9 | 9 | ||
10 | local fs = {} | 10 | local fs = {} |
11 | -- To avoid a loop when loading the other fs modules. | ||
11 | package.loaded["luarocks.fs"] = fs | 12 | package.loaded["luarocks.fs"] = fs |
12 | 13 | ||
13 | local cfg = require("luarocks.cfg") | 14 | local cfg = require("luarocks.core.cfg") |
14 | 15 | ||
15 | local pack = table.pack or function(...) return { n = select("#", ...), ... } end | 16 | local pack = table.pack or function(...) return { n = select("#", ...), ... } end |
16 | local unpack = table.unpack or unpack | 17 | local unpack = table.unpack or unpack |
diff --git a/src/luarocks/fs/lua.lua b/src/luarocks/fs/lua.lua index 841b7243..54da4afd 100644 --- a/src/luarocks/fs/lua.lua +++ b/src/luarocks/fs/lua.lua | |||
@@ -6,7 +6,7 @@ local fs_lua = {} | |||
6 | 6 | ||
7 | local fs = require("luarocks.fs") | 7 | local fs = require("luarocks.fs") |
8 | 8 | ||
9 | local cfg = require("luarocks.cfg") | 9 | local cfg = require("luarocks.core.cfg") |
10 | local dir = require("luarocks.dir") | 10 | local dir = require("luarocks.dir") |
11 | local util = require("luarocks.util") | 11 | local util = require("luarocks.util") |
12 | local path = require("luarocks.path") | 12 | local path = require("luarocks.path") |
@@ -489,10 +489,10 @@ end | |||
489 | 489 | ||
490 | if unzip_ok then | 490 | if unzip_ok then |
491 | --- Uncompress files from a .zip archive. | 491 | --- Uncompress files from a .zip archive. |
492 | -- @param zipfile string: pathname of .zip archive to be extracted. | 492 | -- @param filename string: pathname of .zip archive to be extracted. |
493 | -- @return boolean: true on success, false on failure. | 493 | -- @return boolean: true on success, false on failure. |
494 | function fs_lua.unzip(zipfile) | 494 | function fs_lua.unzip(filename) |
495 | local zipfile, err = luazip.open(zipfile) | 495 | local zipfile, err = luazip.open(filename) |
496 | if not zipfile then return nil, err end | 496 | if not zipfile then return nil, err end |
497 | local files = zipfile:files() | 497 | local files = zipfile:files() |
498 | local file = files() | 498 | local file = files() |
diff --git a/src/luarocks/fs/tools.lua b/src/luarocks/fs/tools.lua index 60d1d9ff..16dc9cf2 100644 --- a/src/luarocks/fs/tools.lua +++ b/src/luarocks/fs/tools.lua | |||
@@ -4,7 +4,7 @@ local tools = {} | |||
4 | 4 | ||
5 | local fs = require("luarocks.fs") | 5 | local fs = require("luarocks.fs") |
6 | local dir = require("luarocks.dir") | 6 | local dir = require("luarocks.dir") |
7 | local cfg = require("luarocks.cfg") | 7 | local cfg = require("luarocks.core.cfg") |
8 | 8 | ||
9 | local vars = cfg.variables | 9 | local vars = cfg.variables |
10 | 10 | ||
diff --git a/src/luarocks/fs/unix.lua b/src/luarocks/fs/unix.lua index 5c51bad5..89e3ec73 100644 --- a/src/luarocks/fs/unix.lua +++ b/src/luarocks/fs/unix.lua | |||
@@ -4,7 +4,7 @@ local unix = {} | |||
4 | 4 | ||
5 | local fs = require("luarocks.fs") | 5 | local fs = require("luarocks.fs") |
6 | 6 | ||
7 | local cfg = require("luarocks.cfg") | 7 | local cfg = require("luarocks.core.cfg") |
8 | local dir = require("luarocks.dir") | 8 | local dir = require("luarocks.dir") |
9 | local util = require("luarocks.util") | 9 | local util = require("luarocks.util") |
10 | 10 | ||
diff --git a/src/luarocks/fs/unix/tools.lua b/src/luarocks/fs/unix/tools.lua index f72001cb..b2ace3b1 100644 --- a/src/luarocks/fs/unix/tools.lua +++ b/src/luarocks/fs/unix/tools.lua | |||
@@ -4,7 +4,7 @@ local tools = {} | |||
4 | 4 | ||
5 | local fs = require("luarocks.fs") | 5 | local fs = require("luarocks.fs") |
6 | local dir = require("luarocks.dir") | 6 | local dir = require("luarocks.dir") |
7 | local cfg = require("luarocks.cfg") | 7 | local cfg = require("luarocks.core.cfg") |
8 | 8 | ||
9 | local vars = cfg.variables | 9 | local vars = cfg.variables |
10 | 10 | ||
diff --git a/src/luarocks/fs/win32.lua b/src/luarocks/fs/win32.lua index 55d69f9f..19c603dc 100644 --- a/src/luarocks/fs/win32.lua +++ b/src/luarocks/fs/win32.lua | |||
@@ -5,7 +5,7 @@ local win32 = {} | |||
5 | 5 | ||
6 | local fs = require("luarocks.fs") | 6 | local fs = require("luarocks.fs") |
7 | 7 | ||
8 | local cfg = require("luarocks.cfg") | 8 | local cfg = require("luarocks.core.cfg") |
9 | local dir = require("luarocks.dir") | 9 | local dir = require("luarocks.dir") |
10 | local util = require("luarocks.util") | 10 | local util = require("luarocks.util") |
11 | 11 | ||
diff --git a/src/luarocks/fs/win32/tools.lua b/src/luarocks/fs/win32/tools.lua index 4adc78d1..7f6b853e 100644 --- a/src/luarocks/fs/win32/tools.lua +++ b/src/luarocks/fs/win32/tools.lua | |||
@@ -6,7 +6,7 @@ local tools = {} | |||
6 | 6 | ||
7 | local fs = require("luarocks.fs") | 7 | local fs = require("luarocks.fs") |
8 | local dir = require("luarocks.dir") | 8 | local dir = require("luarocks.dir") |
9 | local cfg = require("luarocks.cfg") | 9 | local cfg = require("luarocks.core.cfg") |
10 | 10 | ||
11 | local vars = cfg.variables | 11 | local vars = cfg.variables |
12 | 12 | ||
diff --git a/src/luarocks/index.lua b/src/luarocks/index.lua index e1f563ef..80371151 100644 --- a/src/luarocks/index.lua +++ b/src/luarocks/index.lua | |||
@@ -1,11 +1,10 @@ | |||
1 | 1 | ||
2 | --- Module which builds the index.html page to be used in rocks servers. | 2 | --- Module which builds the index.html page to be used in rocks servers. |
3 | local index = {} | 3 | local index = {} |
4 | package.loaded["luarocks.index"] = index | ||
5 | 4 | ||
6 | local util = require("luarocks.util") | 5 | local util = require("luarocks.util") |
7 | local fs = require("luarocks.fs") | 6 | local fs = require("luarocks.fs") |
8 | local deps = require("luarocks.deps") | 7 | local vers = require("luarocks.vers") |
9 | local persist = require("luarocks.persist") | 8 | local persist = require("luarocks.persist") |
10 | local dir = require("luarocks.dir") | 9 | local dir = require("luarocks.dir") |
11 | local manif = require("luarocks.manif") | 10 | local manif = require("luarocks.manif") |
@@ -135,7 +134,7 @@ function index.make_index(repo) | |||
135 | for package, version_list in util.sortedpairs(manifest.repository) do | 134 | for package, version_list in util.sortedpairs(manifest.repository) do |
136 | local latest_rockspec = nil | 135 | local latest_rockspec = nil |
137 | local output = index_package_begin | 136 | local output = index_package_begin |
138 | for version, data in util.sortedpairs(version_list, deps.compare_versions) do | 137 | for version, data in util.sortedpairs(version_list, vers.compare_versions) do |
139 | local versions = {} | 138 | local versions = {} |
140 | output = output..version..': ' | 139 | output = output..version..': ' |
141 | table.sort(data, function(a,b) return a.arch < b.arch end) | 140 | table.sort(data, function(a,b) return a.arch < b.arch end) |
diff --git a/src/luarocks/loader.lua b/src/luarocks/loader.lua index 874bc10c..c8259689 100644 --- a/src/luarocks/loader.lua +++ b/src/luarocks/loader.lua | |||
@@ -6,21 +6,24 @@ | |||
6 | -- used to load previous modules, so that the loader chooses versions | 6 | -- used to load previous modules, so that the loader chooses versions |
7 | -- that are declared to be compatible with the ones loaded earlier. | 7 | -- that are declared to be compatible with the ones loaded earlier. |
8 | local loaders = package.loaders or package.searchers | 8 | local loaders = package.loaders or package.searchers |
9 | local package, require, ipairs, table, type, next, tostring, error = | 9 | local require, ipairs, table, type, next, tostring, error = |
10 | package, require, ipairs, table, type, next, tostring, error | 10 | require, ipairs, table, type, next, tostring, error |
11 | local unpack = unpack or table.unpack | 11 | local unpack = unpack or table.unpack |
12 | 12 | ||
13 | --module("luarocks.loader") | ||
14 | local loader = {} | 13 | local loader = {} |
15 | package.loaded["luarocks.loader"] = loader | ||
16 | 14 | ||
17 | local cfg = require("luarocks.cfg") | 15 | local is_clean = not package.loaded["luarocks.core.cfg"] |
16 | |||
17 | -- This loader module depends only on core modules. | ||
18 | local cfg = require("luarocks.core.cfg") | ||
18 | cfg.init_package_paths() | 19 | cfg.init_package_paths() |
19 | 20 | ||
20 | local path = require("luarocks.path") | 21 | local path = require("luarocks.core.path") |
21 | local manif_core = require("luarocks.manif_core") | 22 | local manif = require("luarocks.core.manif") |
22 | local deps = require("luarocks.deps") | 23 | local vers = require("luarocks.core.vers") |
23 | local util = require("luarocks.util") | 24 | local util = require("luarocks.core.util") |
25 | local require = nil | ||
26 | -------------------------------------------------------------------------------- | ||
24 | 27 | ||
25 | -- Workaround for wrappers produced by older versions of LuaRocks | 28 | -- Workaround for wrappers produced by older versions of LuaRocks |
26 | local temporary_global = false | 29 | local temporary_global = false |
@@ -55,7 +58,7 @@ local function load_rocks_trees() | |||
55 | local any_ok = false | 58 | local any_ok = false |
56 | local trees = {} | 59 | local trees = {} |
57 | for _, tree in ipairs(cfg.rocks_trees) do | 60 | for _, tree in ipairs(cfg.rocks_trees) do |
58 | local manifest, err = manif_core.load_local_manifest(path.rocks_dir(tree)) | 61 | local manifest, err = manif.load_local_manifest(path.rocks_dir(tree)) |
59 | if manifest then | 62 | if manifest then |
60 | any_ok = true | 63 | any_ok = true |
61 | table.insert(trees, {tree=tree, manifest=manifest}) | 64 | table.insert(trees, {tree=tree, manifest=manifest}) |
@@ -109,8 +112,8 @@ function loader.add_context(name, version) | |||
109 | for _, tree in ipairs(loader.rocks_trees) do | 112 | for _, tree in ipairs(loader.rocks_trees) do |
110 | local entries = tree.manifest.repository[pkg] | 113 | local entries = tree.manifest.repository[pkg] |
111 | if entries then | 114 | if entries then |
112 | for version, pkgs in util.sortedpairs(entries, deps.compare_versions) do | 115 | for ver, pkgs in util.sortedpairs(entries, vers.compare_versions) do |
113 | if (not constraints) or deps.match_constraints(deps.parse_version(version), constraints) then | 116 | if (not constraints) or vers.match_constraints(vers.parse_version(ver), constraints) then |
114 | loader.add_context(pkg, version) | 117 | loader.add_context(pkg, version) |
115 | end | 118 | end |
116 | end | 119 | end |
@@ -142,7 +145,7 @@ end | |||
142 | -- @return table or (nil, string): The module table as returned by some other loader, | 145 | -- @return table or (nil, string): The module table as returned by some other loader, |
143 | -- or nil followed by an error message if no other loader managed to load the module. | 146 | -- or nil followed by an error message if no other loader managed to load the module. |
144 | local function call_other_loaders(module, name, version, module_name) | 147 | local function call_other_loaders(module, name, version, module_name) |
145 | for i, a_loader in ipairs(loaders) do | 148 | for _, a_loader in ipairs(loaders) do |
146 | if a_loader ~= loader.luarocks_loader then | 149 | if a_loader ~= loader.luarocks_loader then |
147 | local results = { a_loader(module_name) } | 150 | local results = { a_loader(module_name) } |
148 | if type(results[1]) == "function" then | 151 | if type(results[1]) == "function" then |
@@ -187,7 +190,7 @@ local function select_module(module, filter_file_name) | |||
187 | if loader.context[name] == version then | 190 | if loader.context[name] == version then |
188 | return name, version, file_name | 191 | return name, version, file_name |
189 | end | 192 | end |
190 | version = deps.parse_version(version) | 193 | version = vers.parse_version(version) |
191 | table.insert(providers, {name = name, version = version, module_name = file_name, tree = tree}) | 194 | table.insert(providers, {name = name, version = version, module_name = file_name, tree = tree}) |
192 | end | 195 | end |
193 | end | 196 | end |
@@ -246,4 +249,12 @@ end | |||
246 | 249 | ||
247 | table.insert(loaders, 1, loader.luarocks_loader) | 250 | table.insert(loaders, 1, loader.luarocks_loader) |
248 | 251 | ||
252 | if is_clean then | ||
253 | for modname, _ in pairs(package.loaded) do | ||
254 | if modname:match("^luarocks%.") then | ||
255 | package.loaded[modname] = nil | ||
256 | end | ||
257 | end | ||
258 | end | ||
259 | |||
249 | return loader | 260 | return loader |
diff --git a/src/luarocks/manif.lua b/src/luarocks/manif.lua index 88a13f10..7f3085db 100644 --- a/src/luarocks/manif.lua +++ b/src/luarocks/manif.lua | |||
@@ -3,41 +3,18 @@ | |||
3 | -- They are loaded into manifest tables, which are then used for | 3 | -- They are loaded into manifest tables, which are then used for |
4 | -- performing searches, matching dependencies, etc. | 4 | -- performing searches, matching dependencies, etc. |
5 | local manif = {} | 5 | local manif = {} |
6 | package.loaded["luarocks.manif"] = manif | 6 | setmetatable(manif, { __index = require("luarocks.core.manif") }) |
7 | 7 | ||
8 | local manif_core = require("luarocks.manif_core") | ||
9 | local persist = require("luarocks.persist") | 8 | local persist = require("luarocks.persist") |
10 | local fetch = require("luarocks.fetch") | 9 | local fetch = require("luarocks.fetch") |
11 | local dir = require("luarocks.dir") | 10 | local dir = require("luarocks.dir") |
12 | local fs = require("luarocks.fs") | 11 | local fs = require("luarocks.fs") |
13 | local search = require("luarocks.search") | 12 | local cfg = require("luarocks.core.cfg") |
14 | local util = require("luarocks.util") | ||
15 | local cfg = require("luarocks.cfg") | ||
16 | local path = require("luarocks.path") | 13 | local path = require("luarocks.path") |
17 | local repos = require("luarocks.repos") | 14 | local util = require("luarocks.util") |
18 | local deps = require("luarocks.deps") | ||
19 | 15 | ||
20 | manif.rock_manifest_cache = {} | 16 | manif.rock_manifest_cache = {} |
21 | 17 | ||
22 | --- Commit a table to disk in given local path. | ||
23 | -- @param where string: The directory where the table should be saved. | ||
24 | -- @param name string: The filename. | ||
25 | -- @param tbl table: The table to be saved. | ||
26 | -- @return boolean or (nil, string): true if successful, or nil and a | ||
27 | -- message in case of errors. | ||
28 | local function save_table(where, name, tbl) | ||
29 | assert(type(where) == "string") | ||
30 | assert(type(name) == "string") | ||
31 | assert(type(tbl) == "table") | ||
32 | |||
33 | local filename = dir.path(where, name) | ||
34 | local ok, err = persist.save_from_table(filename..".tmp", tbl) | ||
35 | if ok then | ||
36 | ok, err = fs.replace_file(filename, filename..".tmp") | ||
37 | end | ||
38 | return ok, err | ||
39 | end | ||
40 | |||
41 | function manif.load_rock_manifest(name, version, root) | 18 | function manif.load_rock_manifest(name, version, root) |
42 | assert(type(name) == "string") | 19 | assert(type(name) == "string") |
43 | assert(type(version) == "string") | 20 | assert(type(version) == "string") |
@@ -48,41 +25,13 @@ function manif.load_rock_manifest(name, version, root) | |||
48 | end | 25 | end |
49 | local pathname = path.rock_manifest_file(name, version, root) | 26 | local pathname = path.rock_manifest_file(name, version, root) |
50 | local rock_manifest = persist.load_into_table(pathname) | 27 | local rock_manifest = persist.load_into_table(pathname) |
51 | if not rock_manifest then return nil end | 28 | if not rock_manifest then |
29 | return nil, "rock_manifest file not found for "..name.." "..version.." - not a LuaRocks tree?" | ||
30 | end | ||
52 | manif.rock_manifest_cache[name_version] = rock_manifest | 31 | manif.rock_manifest_cache[name_version] = rock_manifest |
53 | return rock_manifest.rock_manifest | 32 | return rock_manifest.rock_manifest |
54 | end | 33 | end |
55 | 34 | ||
56 | function manif.make_rock_manifest(name, version) | ||
57 | local install_dir = path.install_dir(name, version) | ||
58 | local tree = {} | ||
59 | for _, file in ipairs(fs.find(install_dir)) do | ||
60 | local full_path = dir.path(install_dir, file) | ||
61 | local walk = tree | ||
62 | local last | ||
63 | local last_name | ||
64 | for name in file:gmatch("[^/]+") do | ||
65 | local next = walk[name] | ||
66 | if not next then | ||
67 | next = {} | ||
68 | walk[name] = next | ||
69 | end | ||
70 | last = walk | ||
71 | last_name = name | ||
72 | walk = next | ||
73 | end | ||
74 | if fs.is_file(full_path) then | ||
75 | local sum, err = fs.get_md5(full_path) | ||
76 | if not sum then | ||
77 | return nil, "Failed producing checksum: "..tostring(err) | ||
78 | end | ||
79 | last[last_name] = sum | ||
80 | end | ||
81 | end | ||
82 | local rock_manifest = { rock_manifest=tree } | ||
83 | manif.rock_manifest_cache[name.."/"..version] = rock_manifest | ||
84 | save_table(install_dir, "rock_manifest", rock_manifest ) | ||
85 | end | ||
86 | 35 | ||
87 | local function fetch_manifest_from(repo_url, filename) | 36 | local function fetch_manifest_from(repo_url, filename) |
88 | local url = dir.path(repo_url, filename) | 37 | local url = dir.path(repo_url, filename) |
@@ -111,7 +60,7 @@ function manif.load_manifest(repo_url, lua_version) | |||
111 | assert(type(lua_version) == "string" or not lua_version) | 60 | assert(type(lua_version) == "string" or not lua_version) |
112 | lua_version = lua_version or cfg.lua_version | 61 | lua_version = lua_version or cfg.lua_version |
113 | 62 | ||
114 | local cached_manifest = manif_core.get_cached_manifest(repo_url, lua_version) | 63 | local cached_manifest = manif.get_cached_manifest(repo_url, lua_version) |
115 | if cached_manifest then | 64 | if cached_manifest then |
116 | return cached_manifest | 65 | return cached_manifest |
117 | end | 66 | end |
@@ -158,386 +107,7 @@ function manif.load_manifest(repo_url, lua_version) | |||
158 | end | 107 | end |
159 | pathname = nozip | 108 | pathname = nozip |
160 | end | 109 | end |
161 | return manif_core.manifest_loader(pathname, repo_url, lua_version) | 110 | return manif.manifest_loader(pathname, repo_url, lua_version) |
162 | end | ||
163 | |||
164 | --- Update storage table to account for items provided by a package. | ||
165 | -- @param storage table: a table storing items in the following format: | ||
166 | -- keys are item names and values are arrays of packages providing each item, | ||
167 | -- where a package is specified as string `name/version`. | ||
168 | -- @param items table: a table mapping item names to paths. | ||
169 | -- @param name string: package name. | ||
170 | -- @param version string: package version. | ||
171 | local function store_package_items(storage, name, version, items) | ||
172 | assert(type(storage) == "table") | ||
173 | assert(type(items) == "table") | ||
174 | assert(type(name) == "string") | ||
175 | assert(type(version) == "string") | ||
176 | |||
177 | local package_identifier = name.."/"..version | ||
178 | |||
179 | for item_name, path in pairs(items) do | ||
180 | if not storage[item_name] then | ||
181 | storage[item_name] = {} | ||
182 | end | ||
183 | |||
184 | table.insert(storage[item_name], package_identifier) | ||
185 | end | ||
186 | end | ||
187 | |||
188 | --- Update storage table removing items provided by a package. | ||
189 | -- @param storage table: a table storing items in the following format: | ||
190 | -- keys are item names and values are arrays of packages providing each item, | ||
191 | -- where a package is specified as string `name/version`. | ||
192 | -- @param items table: a table mapping item names to paths. | ||
193 | -- @param name string: package name. | ||
194 | -- @param version string: package version. | ||
195 | local function remove_package_items(storage, name, version, items) | ||
196 | assert(type(storage) == "table") | ||
197 | assert(type(items) == "table") | ||
198 | assert(type(name) == "string") | ||
199 | assert(type(version) == "string") | ||
200 | |||
201 | local package_identifier = name.."/"..version | ||
202 | |||
203 | for item_name, path in pairs(items) do | ||
204 | local all_identifiers = storage[item_name] | ||
205 | |||
206 | for i, identifier in ipairs(all_identifiers) do | ||
207 | if identifier == package_identifier then | ||
208 | table.remove(all_identifiers, i) | ||
209 | break | ||
210 | end | ||
211 | end | ||
212 | |||
213 | if #all_identifiers == 0 then | ||
214 | storage[item_name] = nil | ||
215 | end | ||
216 | end | ||
217 | end | ||
218 | |||
219 | --- Sort function for ordering rock identifiers in a manifest's | ||
220 | -- modules table. Rocks are ordered alphabetically by name, and then | ||
221 | -- by version which greater first. | ||
222 | -- @param a string: Version to compare. | ||
223 | -- @param b string: Version to compare. | ||
224 | -- @return boolean: The comparison result, according to the | ||
225 | -- rule outlined above. | ||
226 | local function sort_pkgs(a, b) | ||
227 | assert(type(a) == "string") | ||
228 | assert(type(b) == "string") | ||
229 | |||
230 | local na, va = a:match("(.*)/(.*)$") | ||
231 | local nb, vb = b:match("(.*)/(.*)$") | ||
232 | |||
233 | return (na == nb) and deps.compare_versions(va, vb) or na < nb | ||
234 | end | ||
235 | |||
236 | --- Sort items of a package matching table by version number (higher versions first). | ||
237 | -- @param tbl table: the package matching table: keys should be strings | ||
238 | -- and values arrays of strings with packages names in "name/version" format. | ||
239 | local function sort_package_matching_table(tbl) | ||
240 | assert(type(tbl) == "table") | ||
241 | |||
242 | if next(tbl) then | ||
243 | for item, pkgs in pairs(tbl) do | ||
244 | if #pkgs > 1 then | ||
245 | table.sort(pkgs, sort_pkgs) | ||
246 | -- Remove duplicates from the sorted array. | ||
247 | local prev = nil | ||
248 | local i = 1 | ||
249 | while pkgs[i] do | ||
250 | local curr = pkgs[i] | ||
251 | if curr == prev then | ||
252 | table.remove(pkgs, i) | ||
253 | else | ||
254 | prev = curr | ||
255 | i = i + 1 | ||
256 | end | ||
257 | end | ||
258 | end | ||
259 | end | ||
260 | end | ||
261 | end | ||
262 | |||
263 | --- Process the dependencies of a manifest table to determine its dependency | ||
264 | -- chains for loading modules. The manifest dependencies information is filled | ||
265 | -- and any dependency inconsistencies or missing dependencies are reported to | ||
266 | -- standard error. | ||
267 | -- @param manifest table: a manifest table. | ||
268 | -- @param deps_mode string: Dependency mode: "one" for the current default tree, | ||
269 | -- "all" for all trees, "order" for all trees with priority >= the current default, | ||
270 | -- "none" for no trees. | ||
271 | local function update_dependencies(manifest, deps_mode) | ||
272 | assert(type(manifest) == "table") | ||
273 | assert(type(deps_mode) == "string") | ||
274 | |||
275 | for pkg, versions in pairs(manifest.repository) do | ||
276 | for version, repositories in pairs(versions) do | ||
277 | for _, repo in ipairs(repositories) do | ||
278 | if repo.arch == "installed" then | ||
279 | repo.dependencies = {} | ||
280 | deps.scan_deps(repo.dependencies, manifest, pkg, version, deps_mode) | ||
281 | repo.dependencies[pkg] = nil | ||
282 | end | ||
283 | end | ||
284 | end | ||
285 | end | ||
286 | end | ||
287 | |||
288 | --- Filter manifest table by Lua version, removing rockspecs whose Lua version | ||
289 | -- does not match. | ||
290 | -- @param manifest table: a manifest table. | ||
291 | -- @param lua_version string or nil: filter by Lua version | ||
292 | -- @param repodir string: directory of repository being scanned | ||
293 | -- @param cache table: temporary rockspec cache table | ||
294 | local function filter_by_lua_version(manifest, lua_version, repodir, cache) | ||
295 | assert(type(manifest) == "table") | ||
296 | assert(type(repodir) == "string") | ||
297 | assert((not cache) or type(cache) == "table") | ||
298 | |||
299 | cache = cache or {} | ||
300 | lua_version = deps.parse_version(lua_version) | ||
301 | for pkg, versions in pairs(manifest.repository) do | ||
302 | local to_remove = {} | ||
303 | for version, repositories in pairs(versions) do | ||
304 | for _, repo in ipairs(repositories) do | ||
305 | if repo.arch == "rockspec" then | ||
306 | local pathname = dir.path(repodir, pkg.."-"..version..".rockspec") | ||
307 | local rockspec, err = cache[pathname] | ||
308 | if not rockspec then | ||
309 | rockspec, err = fetch.load_local_rockspec(pathname, true) | ||
310 | end | ||
311 | if rockspec then | ||
312 | cache[pathname] = rockspec | ||
313 | for _, dep in ipairs(rockspec.dependencies) do | ||
314 | if dep.name == "lua" then | ||
315 | if not deps.match_constraints(lua_version, dep.constraints) then | ||
316 | table.insert(to_remove, version) | ||
317 | end | ||
318 | break | ||
319 | end | ||
320 | end | ||
321 | else | ||
322 | util.printerr("Error loading rockspec for "..pkg.." "..version..": "..err) | ||
323 | end | ||
324 | end | ||
325 | end | ||
326 | end | ||
327 | if next(to_remove) then | ||
328 | for _, incompat in ipairs(to_remove) do | ||
329 | versions[incompat] = nil | ||
330 | end | ||
331 | if not next(versions) then | ||
332 | manifest.repository[pkg] = nil | ||
333 | end | ||
334 | end | ||
335 | end | ||
336 | end | ||
337 | |||
338 | --- Store search results in a manifest table. | ||
339 | -- @param results table: The search results as returned by search.disk_search. | ||
340 | -- @param manifest table: A manifest table (must contain repository, modules, commands tables). | ||
341 | -- It will be altered to include the search results. | ||
342 | -- @return boolean or (nil, string): true in case of success, or nil followed by an error message. | ||
343 | local function store_results(results, manifest) | ||
344 | assert(type(results) == "table") | ||
345 | assert(type(manifest) == "table") | ||
346 | |||
347 | for name, versions in pairs(results) do | ||
348 | local pkgtable = manifest.repository[name] or {} | ||
349 | for version, entries in pairs(versions) do | ||
350 | local versiontable = {} | ||
351 | for _, entry in ipairs(entries) do | ||
352 | local entrytable = {} | ||
353 | entrytable.arch = entry.arch | ||
354 | if entry.arch == "installed" then | ||
355 | local rock_manifest = manif.load_rock_manifest(name, version) | ||
356 | if not rock_manifest then | ||
357 | return nil, "rock_manifest file not found for "..name.." "..version.." - not a LuaRocks 2 tree?" | ||
358 | end | ||
359 | |||
360 | entrytable.modules = repos.package_modules(name, version) | ||
361 | store_package_items(manifest.modules, name, version, entrytable.modules) | ||
362 | entrytable.commands = repos.package_commands(name, version) | ||
363 | store_package_items(manifest.commands, name, version, entrytable.commands) | ||
364 | end | ||
365 | table.insert(versiontable, entrytable) | ||
366 | end | ||
367 | pkgtable[version] = versiontable | ||
368 | end | ||
369 | manifest.repository[name] = pkgtable | ||
370 | end | ||
371 | sort_package_matching_table(manifest.modules) | ||
372 | sort_package_matching_table(manifest.commands) | ||
373 | return true | ||
374 | end | ||
375 | |||
376 | --- Scan a LuaRocks repository and output a manifest file. | ||
377 | -- A file called 'manifest' will be written in the root of the given | ||
378 | -- repository directory. | ||
379 | -- @param repo A local repository directory. | ||
380 | -- @param deps_mode string: Dependency mode: "one" for the current default tree, | ||
381 | -- "all" for all trees, "order" for all trees with priority >= the current default, | ||
382 | -- "none" for the default dependency mode from the configuration. | ||
383 | -- @param remote boolean: 'true' if making a manifest for a rocks server. | ||
384 | -- @return boolean or (nil, string): True if manifest was generated, | ||
385 | -- or nil and an error message. | ||
386 | function manif.make_manifest(repo, deps_mode, remote) | ||
387 | assert(type(repo) == "string") | ||
388 | assert(type(deps_mode) == "string") | ||
389 | |||
390 | if deps_mode == "none" then deps_mode = cfg.deps_mode end | ||
391 | |||
392 | if not fs.is_dir(repo) then | ||
393 | return nil, "Cannot access repository at "..repo | ||
394 | end | ||
395 | |||
396 | local query = search.make_query("") | ||
397 | query.exact_name = false | ||
398 | query.arch = "any" | ||
399 | local results = search.disk_search(repo, query) | ||
400 | local manifest = { repository = {}, modules = {}, commands = {} } | ||
401 | |||
402 | manif_core.cache_manifest(repo, nil, manifest) | ||
403 | |||
404 | local ok, err = store_results(results, manifest) | ||
405 | if not ok then return nil, err end | ||
406 | |||
407 | if remote then | ||
408 | local cache = {} | ||
409 | for luaver in util.lua_versions() do | ||
410 | local vmanifest = { repository = {}, modules = {}, commands = {} } | ||
411 | local ok, err = store_results(results, vmanifest) | ||
412 | filter_by_lua_version(vmanifest, luaver, repo, cache) | ||
413 | save_table(repo, "manifest-"..luaver, vmanifest) | ||
414 | end | ||
415 | else | ||
416 | update_dependencies(manifest, deps_mode) | ||
417 | end | ||
418 | |||
419 | return save_table(repo, "manifest", manifest) | ||
420 | end | ||
421 | |||
422 | --- Update manifest file for a local repository | ||
423 | -- adding information about a version of a package installed in that repository. | ||
424 | -- @param name string: Name of a package from the repository. | ||
425 | -- @param version string: Version of a package from the repository. | ||
426 | -- @param repo string or nil: Pathname of a local repository. If not given, | ||
427 | -- the default local repository is used. | ||
428 | -- @param deps_mode string: Dependency mode: "one" for the current default tree, | ||
429 | -- "all" for all trees, "order" for all trees with priority >= the current default, | ||
430 | -- "none" for using the default dependency mode from the configuration. | ||
431 | -- @return boolean or (nil, string): True if manifest was updated successfully, | ||
432 | -- or nil and an error message. | ||
433 | function manif.add_to_manifest(name, version, repo, deps_mode) | ||
434 | assert(type(name) == "string") | ||
435 | assert(type(version) == "string") | ||
436 | local rocks_dir = path.rocks_dir(repo or cfg.root_dir) | ||
437 | assert(type(deps_mode) == "string") | ||
438 | |||
439 | if deps_mode == "none" then deps_mode = cfg.deps_mode end | ||
440 | |||
441 | local manifest, err = manif_core.load_local_manifest(rocks_dir) | ||
442 | if not manifest then | ||
443 | util.printerr("No existing manifest. Attempting to rebuild...") | ||
444 | -- Manifest built by `manif.make_manifest` should already | ||
445 | -- include information about given name and version, | ||
446 | -- no need to update it. | ||
447 | return manif.make_manifest(rocks_dir, deps_mode) | ||
448 | end | ||
449 | |||
450 | local results = {[name] = {[version] = {{arch = "installed", repo = rocks_dir}}}} | ||
451 | |||
452 | local ok, err = store_results(results, manifest) | ||
453 | if not ok then return nil, err end | ||
454 | |||
455 | update_dependencies(manifest, deps_mode) | ||
456 | return save_table(rocks_dir, "manifest", manifest) | ||
457 | end | ||
458 | |||
459 | --- Update manifest file for a local repository | ||
460 | -- removing information about a version of a package. | ||
461 | -- @param name string: Name of a package removed from the repository. | ||
462 | -- @param version string: Version of a package removed from the repository. | ||
463 | -- @param repo string or nil: Pathname of a local repository. If not given, | ||
464 | -- the default local repository is used. | ||
465 | -- @param deps_mode string: Dependency mode: "one" for the current default tree, | ||
466 | -- "all" for all trees, "order" for all trees with priority >= the current default, | ||
467 | -- "none" for using the default dependency mode from the configuration. | ||
468 | -- @return boolean or (nil, string): True if manifest was updated successfully, | ||
469 | -- or nil and an error message. | ||
470 | function manif.remove_from_manifest(name, version, repo, deps_mode) | ||
471 | assert(type(name) == "string") | ||
472 | assert(type(version) == "string") | ||
473 | local rocks_dir = path.rocks_dir(repo or cfg.root_dir) | ||
474 | assert(type(deps_mode) == "string") | ||
475 | |||
476 | if deps_mode == "none" then deps_mode = cfg.deps_mode end | ||
477 | |||
478 | local manifest, err = manif_core.load_local_manifest(rocks_dir) | ||
479 | if not manifest then | ||
480 | util.printerr("No existing manifest. Attempting to rebuild...") | ||
481 | -- Manifest built by `manif.make_manifest` should already | ||
482 | -- include up-to-date information, no need to update it. | ||
483 | return manif.make_manifest(rocks_dir, deps_mode) | ||
484 | end | ||
485 | |||
486 | local package_entry = manifest.repository[name] | ||
487 | |||
488 | local version_entry = package_entry[version][1] | ||
489 | remove_package_items(manifest.modules, name, version, version_entry.modules) | ||
490 | remove_package_items(manifest.commands, name, version, version_entry.commands) | ||
491 | |||
492 | package_entry[version] = nil | ||
493 | manifest.dependencies[name][version] = nil | ||
494 | |||
495 | if not next(package_entry) then | ||
496 | -- No more versions of this package. | ||
497 | manifest.repository[name] = nil | ||
498 | manifest.dependencies[name] = nil | ||
499 | end | ||
500 | |||
501 | update_dependencies(manifest, deps_mode) | ||
502 | return save_table(rocks_dir, "manifest", manifest) | ||
503 | end | ||
504 | |||
505 | --- Report missing dependencies for all rocks installed in a repository. | ||
506 | -- @param repo string or nil: Pathname of a local repository. If not given, | ||
507 | -- the default local repository is used. | ||
508 | -- @param deps_mode string: Dependency mode: "one" for the current default tree, | ||
509 | -- "all" for all trees, "order" for all trees with priority >= the current default, | ||
510 | -- "none" for using the default dependency mode from the configuration. | ||
511 | function manif.check_dependencies(repo, deps_mode) | ||
512 | local rocks_dir = path.rocks_dir(repo or cfg.root_dir) | ||
513 | assert(type(deps_mode) == "string") | ||
514 | if deps_mode == "none" then deps_mode = cfg.deps_mode end | ||
515 | |||
516 | local manifest = manif_core.load_local_manifest(rocks_dir) | ||
517 | if not manifest then | ||
518 | return | ||
519 | end | ||
520 | |||
521 | for name, versions in util.sortedpairs(manifest.repository) do | ||
522 | for version, version_entries in util.sortedpairs(versions, deps.compare_versions) do | ||
523 | for _, entry in ipairs(version_entries) do | ||
524 | if entry.arch == "installed" then | ||
525 | if manifest.dependencies[name] and manifest.dependencies[name][version] then | ||
526 | deps.report_missing_dependencies(name, version, manifest.dependencies[name][version], deps_mode) | ||
527 | end | ||
528 | end | ||
529 | end | ||
530 | end | ||
531 | end | ||
532 | end | ||
533 | |||
534 | function manif.zip_manifests() | ||
535 | for ver in util.lua_versions() do | ||
536 | local file = "manifest-"..ver | ||
537 | local zip = file..".zip" | ||
538 | fs.delete(dir.path(fs.current_dir(), zip)) | ||
539 | fs.zip(zip, file) | ||
540 | end | ||
541 | end | 111 | end |
542 | 112 | ||
543 | --- Get type and name of an item (a module or a command) provided by a file. | 113 | --- Get type and name of an item (a module or a command) provided by a file. |
@@ -556,7 +126,7 @@ local function get_providers(item_type, item_name, repo) | |||
556 | assert(type(item_type) == "string") | 126 | assert(type(item_type) == "string") |
557 | assert(type(item_name) == "string") | 127 | assert(type(item_name) == "string") |
558 | local rocks_dir = path.rocks_dir(repo or cfg.root_dir) | 128 | local rocks_dir = path.rocks_dir(repo or cfg.root_dir) |
559 | local manifest = manif_core.load_local_manifest(rocks_dir) | 129 | local manifest = manif.load_local_manifest(rocks_dir) |
560 | return manifest and manifest[item_type .. "s"][item_name] | 130 | return manifest and manifest[item_type .. "s"][item_name] |
561 | end | 131 | end |
562 | 132 | ||
@@ -592,7 +162,7 @@ end | |||
592 | -- and path to the providing file relatively to that subtree. | 162 | -- and path to the providing file relatively to that subtree. |
593 | function manif.get_providing_file(name, version, item_type, item_name, repo) | 163 | function manif.get_providing_file(name, version, item_type, item_name, repo) |
594 | local rocks_dir = path.rocks_dir(repo or cfg.root_dir) | 164 | local rocks_dir = path.rocks_dir(repo or cfg.root_dir) |
595 | local manifest = manif_core.load_local_manifest(rocks_dir) | 165 | local manifest = manif.load_local_manifest(rocks_dir) |
596 | 166 | ||
597 | local entry_table = manifest.repository[name][version][1] | 167 | local entry_table = manifest.repository[name][version][1] |
598 | local file_path = entry_table[item_type .. "s"][item_name] | 168 | local file_path = entry_table[item_type .. "s"][item_name] |
@@ -625,4 +195,30 @@ function manif.get_providing_file(name, version, item_type, item_name, repo) | |||
625 | return type(subtree) == "string" and "lib" or "lua", file_path | 195 | return type(subtree) == "string" and "lib" or "lua", file_path |
626 | end | 196 | end |
627 | 197 | ||
198 | --- Get all versions of a package listed in a manifest file. | ||
199 | -- @param name string: a package name. | ||
200 | -- @param deps_mode string: "one", to use only the currently | ||
201 | -- configured tree; "order" to select trees based on order | ||
202 | -- (use the current tree and all trees below it on the list) | ||
203 | -- or "all", to use all trees. | ||
204 | -- @return table: An array of strings listing installed | ||
205 | -- versions of a package. | ||
206 | function manif.get_versions(name, deps_mode) | ||
207 | assert(type(name) == "string") | ||
208 | assert(type(deps_mode) == "string") | ||
209 | |||
210 | local version_set = {} | ||
211 | path.map_trees(deps_mode, function(tree) | ||
212 | local manifest = manif.load_local_manifest(path.rocks_dir(tree)) | ||
213 | |||
214 | if manifest and manifest.repository[name] then | ||
215 | for version in pairs(manifest.repository[name]) do | ||
216 | version_set[version] = true | ||
217 | end | ||
218 | end | ||
219 | end) | ||
220 | |||
221 | return util.keys(version_set) | ||
222 | end | ||
223 | |||
628 | return manif | 224 | return manif |
diff --git a/src/luarocks/manif/writer.lua b/src/luarocks/manif/writer.lua new file mode 100644 index 00000000..2d17d328 --- /dev/null +++ b/src/luarocks/manif/writer.lua | |||
@@ -0,0 +1,437 @@ | |||
1 | |||
2 | local writer = {} | ||
3 | |||
4 | local cfg = require("luarocks.core.cfg") | ||
5 | local search = require("luarocks.search") | ||
6 | local repos = require("luarocks.repos") | ||
7 | local deps = require("luarocks.deps") | ||
8 | local vers = require("luarocks.vers") | ||
9 | local fs = require("luarocks.fs") | ||
10 | local util = require("luarocks.util") | ||
11 | local dir = require("luarocks.dir") | ||
12 | local fetch = require("luarocks.fetch") | ||
13 | local path = require("luarocks.path") | ||
14 | local persist = require("luarocks.persist") | ||
15 | local manif = require("luarocks.manif") | ||
16 | |||
17 | --- Update storage table to account for items provided by a package. | ||
18 | -- @param storage table: a table storing items in the following format: | ||
19 | -- keys are item names and values are arrays of packages providing each item, | ||
20 | -- where a package is specified as string `name/version`. | ||
21 | -- @param items table: a table mapping item names to paths. | ||
22 | -- @param name string: package name. | ||
23 | -- @param version string: package version. | ||
24 | local function store_package_items(storage, name, version, items) | ||
25 | assert(type(storage) == "table") | ||
26 | assert(type(items) == "table") | ||
27 | assert(type(name) == "string") | ||
28 | assert(type(version) == "string") | ||
29 | |||
30 | local package_identifier = name.."/"..version | ||
31 | |||
32 | for item_name, path in pairs(items) do | ||
33 | if not storage[item_name] then | ||
34 | storage[item_name] = {} | ||
35 | end | ||
36 | |||
37 | table.insert(storage[item_name], package_identifier) | ||
38 | end | ||
39 | end | ||
40 | |||
41 | --- Update storage table removing items provided by a package. | ||
42 | -- @param storage table: a table storing items in the following format: | ||
43 | -- keys are item names and values are arrays of packages providing each item, | ||
44 | -- where a package is specified as string `name/version`. | ||
45 | -- @param items table: a table mapping item names to paths. | ||
46 | -- @param name string: package name. | ||
47 | -- @param version string: package version. | ||
48 | local function remove_package_items(storage, name, version, items) | ||
49 | assert(type(storage) == "table") | ||
50 | assert(type(items) == "table") | ||
51 | assert(type(name) == "string") | ||
52 | assert(type(version) == "string") | ||
53 | |||
54 | local package_identifier = name.."/"..version | ||
55 | |||
56 | for item_name, path in pairs(items) do | ||
57 | local all_identifiers = storage[item_name] | ||
58 | |||
59 | for i, identifier in ipairs(all_identifiers) do | ||
60 | if identifier == package_identifier then | ||
61 | table.remove(all_identifiers, i) | ||
62 | break | ||
63 | end | ||
64 | end | ||
65 | |||
66 | if #all_identifiers == 0 then | ||
67 | storage[item_name] = nil | ||
68 | end | ||
69 | end | ||
70 | end | ||
71 | |||
72 | --- Process the dependencies of a manifest table to determine its dependency | ||
73 | -- chains for loading modules. The manifest dependencies information is filled | ||
74 | -- and any dependency inconsistencies or missing dependencies are reported to | ||
75 | -- standard error. | ||
76 | -- @param manifest table: a manifest table. | ||
77 | -- @param deps_mode string: Dependency mode: "one" for the current default tree, | ||
78 | -- "all" for all trees, "order" for all trees with priority >= the current default, | ||
79 | -- "none" for no trees. | ||
80 | local function update_dependencies(manifest, deps_mode) | ||
81 | assert(type(manifest) == "table") | ||
82 | assert(type(deps_mode) == "string") | ||
83 | |||
84 | for pkg, versions in pairs(manifest.repository) do | ||
85 | for version, repositories in pairs(versions) do | ||
86 | for _, repo in ipairs(repositories) do | ||
87 | if repo.arch == "installed" then | ||
88 | repo.dependencies = {} | ||
89 | deps.scan_deps(repo.dependencies, manifest, pkg, version, deps_mode) | ||
90 | repo.dependencies[pkg] = nil | ||
91 | end | ||
92 | end | ||
93 | end | ||
94 | end | ||
95 | end | ||
96 | |||
97 | |||
98 | |||
99 | --- Sort function for ordering rock identifiers in a manifest's | ||
100 | -- modules table. Rocks are ordered alphabetically by name, and then | ||
101 | -- by version which greater first. | ||
102 | -- @param a string: Version to compare. | ||
103 | -- @param b string: Version to compare. | ||
104 | -- @return boolean: The comparison result, according to the | ||
105 | -- rule outlined above. | ||
106 | local function sort_pkgs(a, b) | ||
107 | assert(type(a) == "string") | ||
108 | assert(type(b) == "string") | ||
109 | |||
110 | local na, va = a:match("(.*)/(.*)$") | ||
111 | local nb, vb = b:match("(.*)/(.*)$") | ||
112 | |||
113 | return (na == nb) and vers.compare_versions(va, vb) or na < nb | ||
114 | end | ||
115 | |||
116 | --- Sort items of a package matching table by version number (higher versions first). | ||
117 | -- @param tbl table: the package matching table: keys should be strings | ||
118 | -- and values arrays of strings with packages names in "name/version" format. | ||
119 | local function sort_package_matching_table(tbl) | ||
120 | assert(type(tbl) == "table") | ||
121 | |||
122 | if next(tbl) then | ||
123 | for item, pkgs in pairs(tbl) do | ||
124 | if #pkgs > 1 then | ||
125 | table.sort(pkgs, sort_pkgs) | ||
126 | -- Remove duplicates from the sorted array. | ||
127 | local prev = nil | ||
128 | local i = 1 | ||
129 | while pkgs[i] do | ||
130 | local curr = pkgs[i] | ||
131 | if curr == prev then | ||
132 | table.remove(pkgs, i) | ||
133 | else | ||
134 | prev = curr | ||
135 | i = i + 1 | ||
136 | end | ||
137 | end | ||
138 | end | ||
139 | end | ||
140 | end | ||
141 | end | ||
142 | |||
143 | --- Filter manifest table by Lua version, removing rockspecs whose Lua version | ||
144 | -- does not match. | ||
145 | -- @param manifest table: a manifest table. | ||
146 | -- @param lua_version string or nil: filter by Lua version | ||
147 | -- @param repodir string: directory of repository being scanned | ||
148 | -- @param cache table: temporary rockspec cache table | ||
149 | local function filter_by_lua_version(manifest, lua_version, repodir, cache) | ||
150 | assert(type(manifest) == "table") | ||
151 | assert(type(repodir) == "string") | ||
152 | assert((not cache) or type(cache) == "table") | ||
153 | |||
154 | cache = cache or {} | ||
155 | lua_version = vers.parse_version(lua_version) | ||
156 | for pkg, versions in pairs(manifest.repository) do | ||
157 | local to_remove = {} | ||
158 | for version, repositories in pairs(versions) do | ||
159 | for _, repo in ipairs(repositories) do | ||
160 | if repo.arch == "rockspec" then | ||
161 | local pathname = dir.path(repodir, pkg.."-"..version..".rockspec") | ||
162 | local rockspec, err = cache[pathname] | ||
163 | if not rockspec then | ||
164 | rockspec, err = fetch.load_local_rockspec(pathname, true) | ||
165 | end | ||
166 | if rockspec then | ||
167 | cache[pathname] = rockspec | ||
168 | for _, dep in ipairs(rockspec.dependencies) do | ||
169 | if dep.name == "lua" then | ||
170 | if not vers.match_constraints(lua_version, dep.constraints) then | ||
171 | table.insert(to_remove, version) | ||
172 | end | ||
173 | break | ||
174 | end | ||
175 | end | ||
176 | else | ||
177 | util.printerr("Error loading rockspec for "..pkg.." "..version..": "..err) | ||
178 | end | ||
179 | end | ||
180 | end | ||
181 | end | ||
182 | if next(to_remove) then | ||
183 | for _, incompat in ipairs(to_remove) do | ||
184 | versions[incompat] = nil | ||
185 | end | ||
186 | if not next(versions) then | ||
187 | manifest.repository[pkg] = nil | ||
188 | end | ||
189 | end | ||
190 | end | ||
191 | end | ||
192 | |||
193 | --- Store search results in a manifest table. | ||
194 | -- @param results table: The search results as returned by search.disk_search. | ||
195 | -- @param manifest table: A manifest table (must contain repository, modules, commands tables). | ||
196 | -- It will be altered to include the search results. | ||
197 | -- @return boolean or (nil, string): true in case of success, or nil followed by an error message. | ||
198 | local function store_results(results, manifest) | ||
199 | assert(type(results) == "table") | ||
200 | assert(type(manifest) == "table") | ||
201 | |||
202 | for name, versions in pairs(results) do | ||
203 | local pkgtable = manifest.repository[name] or {} | ||
204 | for version, entries in pairs(versions) do | ||
205 | local versiontable = {} | ||
206 | for _, entry in ipairs(entries) do | ||
207 | local entrytable = {} | ||
208 | entrytable.arch = entry.arch | ||
209 | if entry.arch == "installed" then | ||
210 | local rock_manifest, err = manif.load_rock_manifest(name, version) | ||
211 | if not rock_manifest then return nil, err end | ||
212 | |||
213 | entrytable.modules = repos.package_modules(name, version) | ||
214 | store_package_items(manifest.modules, name, version, entrytable.modules) | ||
215 | entrytable.commands = repos.package_commands(name, version) | ||
216 | store_package_items(manifest.commands, name, version, entrytable.commands) | ||
217 | end | ||
218 | table.insert(versiontable, entrytable) | ||
219 | end | ||
220 | pkgtable[version] = versiontable | ||
221 | end | ||
222 | manifest.repository[name] = pkgtable | ||
223 | end | ||
224 | sort_package_matching_table(manifest.modules) | ||
225 | sort_package_matching_table(manifest.commands) | ||
226 | return true | ||
227 | end | ||
228 | |||
229 | --- Commit a table to disk in given local path. | ||
230 | -- @param where string: The directory where the table should be saved. | ||
231 | -- @param name string: The filename. | ||
232 | -- @param tbl table: The table to be saved. | ||
233 | -- @return boolean or (nil, string): true if successful, or nil and a | ||
234 | -- message in case of errors. | ||
235 | local function save_table(where, name, tbl) | ||
236 | assert(type(where) == "string") | ||
237 | assert(type(name) == "string") | ||
238 | assert(type(tbl) == "table") | ||
239 | |||
240 | local filename = dir.path(where, name) | ||
241 | local ok, err = persist.save_from_table(filename..".tmp", tbl) | ||
242 | if ok then | ||
243 | ok, err = fs.replace_file(filename, filename..".tmp") | ||
244 | end | ||
245 | return ok, err | ||
246 | end | ||
247 | |||
248 | function writer.make_rock_manifest(name, version) | ||
249 | local install_dir = path.install_dir(name, version) | ||
250 | local tree = {} | ||
251 | for _, file in ipairs(fs.find(install_dir)) do | ||
252 | local full_path = dir.path(install_dir, file) | ||
253 | local walk = tree | ||
254 | local last | ||
255 | local last_name | ||
256 | for filename in file:gmatch("[^/]+") do | ||
257 | local next = walk[filename] | ||
258 | if not next then | ||
259 | next = {} | ||
260 | walk[filename] = next | ||
261 | end | ||
262 | last = walk | ||
263 | last_name = filename | ||
264 | walk = next | ||
265 | end | ||
266 | if fs.is_file(full_path) then | ||
267 | local sum, err = fs.get_md5(full_path) | ||
268 | if not sum then | ||
269 | return nil, "Failed producing checksum: "..tostring(err) | ||
270 | end | ||
271 | last[last_name] = sum | ||
272 | end | ||
273 | end | ||
274 | local rock_manifest = { rock_manifest=tree } | ||
275 | manif.rock_manifest_cache[name.."/"..version] = rock_manifest | ||
276 | save_table(install_dir, "rock_manifest", rock_manifest ) | ||
277 | end | ||
278 | |||
279 | --- Scan a LuaRocks repository and output a manifest file. | ||
280 | -- A file called 'manifest' will be written in the root of the given | ||
281 | -- repository directory. | ||
282 | -- @param repo A local repository directory. | ||
283 | -- @param deps_mode string: Dependency mode: "one" for the current default tree, | ||
284 | -- "all" for all trees, "order" for all trees with priority >= the current default, | ||
285 | -- "none" for the default dependency mode from the configuration. | ||
286 | -- @param remote boolean: 'true' if making a manifest for a rocks server. | ||
287 | -- @return boolean or (nil, string): True if manifest was generated, | ||
288 | -- or nil and an error message. | ||
289 | function writer.make_manifest(repo, deps_mode, remote) | ||
290 | assert(type(repo) == "string") | ||
291 | assert(type(deps_mode) == "string") | ||
292 | |||
293 | if deps_mode == "none" then deps_mode = cfg.deps_mode end | ||
294 | |||
295 | if not fs.is_dir(repo) then | ||
296 | return nil, "Cannot access repository at "..repo | ||
297 | end | ||
298 | |||
299 | local query = search.make_query("") | ||
300 | query.exact_name = false | ||
301 | query.arch = "any" | ||
302 | local results = search.disk_search(repo, query) | ||
303 | local manifest = { repository = {}, modules = {}, commands = {} } | ||
304 | |||
305 | manif.cache_manifest(repo, nil, manifest) | ||
306 | |||
307 | local ok, err = store_results(results, manifest) | ||
308 | if not ok then return nil, err end | ||
309 | |||
310 | if remote then | ||
311 | local cache = {} | ||
312 | for luaver in util.lua_versions() do | ||
313 | local vmanifest = { repository = {}, modules = {}, commands = {} } | ||
314 | local ok, err = store_results(results, vmanifest) | ||
315 | filter_by_lua_version(vmanifest, luaver, repo, cache) | ||
316 | save_table(repo, "manifest-"..luaver, vmanifest) | ||
317 | end | ||
318 | else | ||
319 | update_dependencies(manifest, deps_mode) | ||
320 | end | ||
321 | |||
322 | return save_table(repo, "manifest", manifest) | ||
323 | end | ||
324 | |||
325 | --- Update manifest file for a local repository | ||
326 | -- adding information about a version of a package installed in that repository. | ||
327 | -- @param name string: Name of a package from the repository. | ||
328 | -- @param version string: Version of a package from the repository. | ||
329 | -- @param repo string or nil: Pathname of a local repository. If not given, | ||
330 | -- the default local repository is used. | ||
331 | -- @param deps_mode string: Dependency mode: "one" for the current default tree, | ||
332 | -- "all" for all trees, "order" for all trees with priority >= the current default, | ||
333 | -- "none" for using the default dependency mode from the configuration. | ||
334 | -- @return boolean or (nil, string): True if manifest was updated successfully, | ||
335 | -- or nil and an error message. | ||
336 | function writer.add_to_manifest(name, version, repo, deps_mode) | ||
337 | assert(type(name) == "string") | ||
338 | assert(type(version) == "string") | ||
339 | local rocks_dir = path.rocks_dir(repo or cfg.root_dir) | ||
340 | assert(type(deps_mode) == "string") | ||
341 | |||
342 | if deps_mode == "none" then deps_mode = cfg.deps_mode end | ||
343 | |||
344 | local manifest, err = manif.load_local_manifest(rocks_dir) | ||
345 | if not manifest then | ||
346 | util.printerr("No existing manifest. Attempting to rebuild...") | ||
347 | -- Manifest built by `writer.make_manifest` should already | ||
348 | -- include information about given name and version, | ||
349 | -- no need to update it. | ||
350 | return writer.make_manifest(rocks_dir, deps_mode) | ||
351 | end | ||
352 | |||
353 | local results = {[name] = {[version] = {{arch = "installed", repo = rocks_dir}}}} | ||
354 | |||
355 | local ok, err = store_results(results, manifest) | ||
356 | if not ok then return nil, err end | ||
357 | |||
358 | update_dependencies(manifest, deps_mode) | ||
359 | return save_table(rocks_dir, "manifest", manifest) | ||
360 | end | ||
361 | |||
362 | --- Update manifest file for a local repository | ||
363 | -- removing information about a version of a package. | ||
364 | -- @param name string: Name of a package removed from the repository. | ||
365 | -- @param version string: Version of a package removed from the repository. | ||
366 | -- @param repo string or nil: Pathname of a local repository. If not given, | ||
367 | -- the default local repository is used. | ||
368 | -- @param deps_mode string: Dependency mode: "one" for the current default tree, | ||
369 | -- "all" for all trees, "order" for all trees with priority >= the current default, | ||
370 | -- "none" for using the default dependency mode from the configuration. | ||
371 | -- @return boolean or (nil, string): True if manifest was updated successfully, | ||
372 | -- or nil and an error message. | ||
373 | function writer.remove_from_manifest(name, version, repo, deps_mode) | ||
374 | assert(type(name) == "string") | ||
375 | assert(type(version) == "string") | ||
376 | local rocks_dir = path.rocks_dir(repo or cfg.root_dir) | ||
377 | assert(type(deps_mode) == "string") | ||
378 | |||
379 | if deps_mode == "none" then deps_mode = cfg.deps_mode end | ||
380 | |||
381 | local manifest, err = manif.load_local_manifest(rocks_dir) | ||
382 | if not manifest then | ||
383 | util.printerr("No existing manifest. Attempting to rebuild...") | ||
384 | -- Manifest built by `writer.make_manifest` should already | ||
385 | -- include up-to-date information, no need to update it. | ||
386 | return writer.make_manifest(rocks_dir, deps_mode) | ||
387 | end | ||
388 | |||
389 | local package_entry = manifest.repository[name] | ||
390 | |||
391 | local version_entry = package_entry[version][1] | ||
392 | remove_package_items(manifest.modules, name, version, version_entry.modules) | ||
393 | remove_package_items(manifest.commands, name, version, version_entry.commands) | ||
394 | |||
395 | package_entry[version] = nil | ||
396 | manifest.dependencies[name][version] = nil | ||
397 | |||
398 | if not next(package_entry) then | ||
399 | -- No more versions of this package. | ||
400 | manifest.repository[name] = nil | ||
401 | manifest.dependencies[name] = nil | ||
402 | end | ||
403 | |||
404 | update_dependencies(manifest, deps_mode) | ||
405 | return save_table(rocks_dir, "manifest", manifest) | ||
406 | end | ||
407 | |||
408 | --- Report missing dependencies for all rocks installed in a repository. | ||
409 | -- @param repo string or nil: Pathname of a local repository. If not given, | ||
410 | -- the default local repository is used. | ||
411 | -- @param deps_mode string: Dependency mode: "one" for the current default tree, | ||
412 | -- "all" for all trees, "order" for all trees with priority >= the current default, | ||
413 | -- "none" for using the default dependency mode from the configuration. | ||
414 | function writer.check_dependencies(repo, deps_mode) | ||
415 | local rocks_dir = path.rocks_dir(repo or cfg.root_dir) | ||
416 | assert(type(deps_mode) == "string") | ||
417 | if deps_mode == "none" then deps_mode = cfg.deps_mode end | ||
418 | |||
419 | local manifest = manif.load_local_manifest(rocks_dir) | ||
420 | if not manifest then | ||
421 | return | ||
422 | end | ||
423 | |||
424 | for name, versions in util.sortedpairs(manifest.repository) do | ||
425 | for version, version_entries in util.sortedpairs(versions, vers.compare_versions) do | ||
426 | for _, entry in ipairs(version_entries) do | ||
427 | if entry.arch == "installed" then | ||
428 | if manifest.dependencies[name] and manifest.dependencies[name][version] then | ||
429 | deps.report_missing_dependencies(name, version, manifest.dependencies[name][version], deps_mode, cfg.rocks_provided_3_0) | ||
430 | end | ||
431 | end | ||
432 | end | ||
433 | end | ||
434 | end | ||
435 | end | ||
436 | |||
437 | return writer | ||
diff --git a/src/luarocks/pack.lua b/src/luarocks/pack.lua index 35bbe838..b721a209 100644 --- a/src/luarocks/pack.lua +++ b/src/luarocks/pack.lua | |||
@@ -1,8 +1,6 @@ | |||
1 | 1 | ||
2 | --- Module implementing the LuaRocks "pack" command. | 2 | -- Create rock files, packing sources or binaries. |
3 | -- Creates a rock, packing sources or binaries. | ||
4 | local pack = {} | 3 | local pack = {} |
5 | package.loaded["luarocks.pack"] = pack | ||
6 | 4 | ||
7 | local unpack = unpack or table.unpack | 5 | local unpack = unpack or table.unpack |
8 | 6 | ||
@@ -10,22 +8,12 @@ local path = require("luarocks.path") | |||
10 | local repos = require("luarocks.repos") | 8 | local repos = require("luarocks.repos") |
11 | local fetch = require("luarocks.fetch") | 9 | local fetch = require("luarocks.fetch") |
12 | local fs = require("luarocks.fs") | 10 | local fs = require("luarocks.fs") |
13 | local cfg = require("luarocks.cfg") | 11 | local cfg = require("luarocks.core.cfg") |
14 | local util = require("luarocks.util") | 12 | local util = require("luarocks.util") |
15 | local dir = require("luarocks.dir") | 13 | local dir = require("luarocks.dir") |
16 | local manif = require("luarocks.manif") | 14 | local manif = require("luarocks.manif") |
17 | local search = require("luarocks.search") | 15 | local search = require("luarocks.search") |
18 | 16 | ||
19 | util.add_run_function(pack) | ||
20 | pack.help_summary = "Create a rock, packing sources or binaries." | ||
21 | pack.help_arguments = "{<rockspec>|<name> [<version>]}" | ||
22 | pack.help = [[ | ||
23 | Argument may be a rockspec file, for creating a source rock, | ||
24 | or the name of an installed package, for creating a binary rock. | ||
25 | In the latter case, the app version may be given as a second | ||
26 | argument. | ||
27 | ]] | ||
28 | |||
29 | --- Create a source rock. | 17 | --- Create a source rock. |
30 | -- Packages a rockspec and its required source files in a rock | 18 | -- Packages a rockspec and its required source files in a rock |
31 | -- file with the .src.rock extension, which can later be built and | 19 | -- file with the .src.rock extension, which can later be built and |
@@ -88,7 +76,7 @@ end | |||
88 | -- @param tree string or nil: An optional tree to pick the package from. | 76 | -- @param tree string or nil: An optional tree to pick the package from. |
89 | -- @return string or (nil, string): The filename of the resulting | 77 | -- @return string or (nil, string): The filename of the resulting |
90 | -- .src.rock file; or nil and an error message. | 78 | -- .src.rock file; or nil and an error message. |
91 | local function do_pack_binary_rock(name, version, tree) | 79 | function pack.pack_installed_rock(name, version, tree) |
92 | assert(type(name) == "string") | 80 | assert(type(name) == "string") |
93 | assert(type(version) == "string" or not version) | 81 | assert(type(version) == "string" or not version) |
94 | 82 | ||
@@ -104,10 +92,8 @@ local function do_pack_binary_rock(name, version, tree) | |||
104 | return nil, "'"..name.." "..version.."' does not seem to be an installed rock." | 92 | return nil, "'"..name.." "..version.."' does not seem to be an installed rock." |
105 | end | 93 | end |
106 | 94 | ||
107 | local rock_manifest = manif.load_rock_manifest(name, version, root) | 95 | local rock_manifest, err = manif.load_rock_manifest(name, version, root) |
108 | if not rock_manifest then | 96 | if not rock_manifest then return nil, err end |
109 | return nil, "rock_manifest file not found for "..name.." "..version.." - not a LuaRocks 2 tree?" | ||
110 | end | ||
111 | 97 | ||
112 | local name_version = name .. "-" .. version | 98 | local name_version = name .. "-" .. version |
113 | local rock_file = fs.absolute_name(name_version .. "."..cfg.arch..".rock") | 99 | local rock_file = fs.absolute_name(name_version .. "."..cfg.arch..".rock") |
@@ -164,34 +150,7 @@ function pack.pack_binary_rock(name, version, cmd, ...) | |||
164 | if not rname then | 150 | if not rname then |
165 | rname, rversion = name, version | 151 | rname, rversion = name, version |
166 | end | 152 | end |
167 | return do_pack_binary_rock(rname, rversion, temp_dir) | 153 | return pack.pack_installed_rock(rname, rversion, temp_dir) |
168 | end | ||
169 | |||
170 | --- Driver function for the "pack" command. | ||
171 | -- @param arg string: may be a rockspec file, for creating a source rock, | ||
172 | -- or the name of an installed package, for creating a binary rock. | ||
173 | -- @param version string or nil: if the name of a package is given, a | ||
174 | -- version may also be passed. | ||
175 | -- @return boolean or (nil, string): true if successful or nil followed | ||
176 | -- by an error message. | ||
177 | function pack.command(flags, arg, version) | ||
178 | assert(type(version) == "string" or not version) | ||
179 | if type(arg) ~= "string" then | ||
180 | return nil, "Argument missing. "..util.see_help("pack") | ||
181 | end | ||
182 | |||
183 | local file, err | ||
184 | if arg:match(".*%.rockspec") then | ||
185 | file, err = pack.pack_source_rock(arg) | ||
186 | else | ||
187 | file, err = do_pack_binary_rock(arg:lower(), version, flags["tree"]) | ||
188 | end | ||
189 | if err then | ||
190 | return nil, err | ||
191 | else | ||
192 | util.printout("Packed: "..file) | ||
193 | return true | ||
194 | end | ||
195 | end | 154 | end |
196 | 155 | ||
197 | return pack | 156 | return pack |
diff --git a/src/luarocks/path.lua b/src/luarocks/path.lua index dafc64e7..37898435 100644 --- a/src/luarocks/path.lua +++ b/src/luarocks/path.lua | |||
@@ -3,9 +3,10 @@ | |||
3 | -- All paths are configured in this module, making it a single | 3 | -- All paths are configured in this module, making it a single |
4 | -- point where the layout of the local installation is defined in LuaRocks. | 4 | -- point where the layout of the local installation is defined in LuaRocks. |
5 | local path = {} | 5 | local path = {} |
6 | setmetatable(path, { __index = require("luarocks.core.path") }) | ||
6 | 7 | ||
7 | local dir = require("luarocks.dir") | 8 | local dir = require("luarocks.dir") |
8 | local cfg = require("luarocks.cfg") | 9 | local cfg = require("luarocks.core.cfg") |
9 | local util = require("luarocks.util") | 10 | local util = require("luarocks.util") |
10 | 11 | ||
11 | --- Infer rockspec filename from a rock filename. | 12 | --- Infer rockspec filename from a rock filename. |
@@ -17,29 +18,11 @@ function path.rockspec_name_from_rock(rock_name) | |||
17 | return base_name:match("(.*)%.[^.]*.rock") .. ".rockspec" | 18 | return base_name:match("(.*)%.[^.]*.rock") .. ".rockspec" |
18 | end | 19 | end |
19 | 20 | ||
20 | function path.rocks_dir(tree) | ||
21 | if type(tree) == "string" then | ||
22 | return dir.path(tree, cfg.rocks_subdir) | ||
23 | else | ||
24 | assert(type(tree) == "table") | ||
25 | return tree.rocks_dir or dir.path(tree.root, cfg.rocks_subdir) | ||
26 | end | ||
27 | end | ||
28 | |||
29 | function path.root_dir(rocks_dir) | 21 | function path.root_dir(rocks_dir) |
30 | assert(type(rocks_dir) == "string") | 22 | assert(type(rocks_dir) == "string") |
31 | return rocks_dir:match("(.*)" .. util.matchquote(cfg.rocks_subdir) .. ".*$") | 23 | return rocks_dir:match("(.*)" .. util.matchquote(cfg.rocks_subdir) .. ".*$") |
32 | end | 24 | end |
33 | 25 | ||
34 | function path.rocks_tree_to_string(tree) | ||
35 | if type(tree) == "string" then | ||
36 | return tree | ||
37 | else | ||
38 | assert(type(tree) == "table") | ||
39 | return tree.root | ||
40 | end | ||
41 | end | ||
42 | |||
43 | function path.deploy_bin_dir(tree) | 26 | function path.deploy_bin_dir(tree) |
44 | if type(tree) == "string" then | 27 | if type(tree) == "string" then |
45 | return dir.path(tree, "bin") | 28 | return dir.path(tree, "bin") |
@@ -49,24 +32,6 @@ function path.deploy_bin_dir(tree) | |||
49 | end | 32 | end |
50 | end | 33 | end |
51 | 34 | ||
52 | function path.deploy_lua_dir(tree) | ||
53 | if type(tree) == "string" then | ||
54 | return dir.path(tree, cfg.lua_modules_path) | ||
55 | else | ||
56 | assert(type(tree) == "table") | ||
57 | return tree.lua_dir or dir.path(tree.root, cfg.lua_modules_path) | ||
58 | end | ||
59 | end | ||
60 | |||
61 | function path.deploy_lib_dir(tree) | ||
62 | if type(tree) == "string" then | ||
63 | return dir.path(tree, cfg.lib_modules_path) | ||
64 | else | ||
65 | assert(type(tree) == "table") | ||
66 | return tree.lib_dir or dir.path(tree.root, cfg.lib_modules_path) | ||
67 | end | ||
68 | end | ||
69 | |||
70 | function path.manifest_file(tree) | 35 | function path.manifest_file(tree) |
71 | if type(tree) == "string" then | 36 | if type(tree) == "string" then |
72 | return dir.path(tree, cfg.rocks_subdir, "manifest") | 37 | return dir.path(tree, cfg.rocks_subdir, "manifest") |
@@ -229,34 +194,6 @@ function path.make_url(pathname, name, version, arch) | |||
229 | return dir.path(pathname, filename) | 194 | return dir.path(pathname, filename) |
230 | end | 195 | end |
231 | 196 | ||
232 | --- Convert a pathname to a module identifier. | ||
233 | -- In Unix, for example, a path "foo/bar/baz.lua" is converted to | ||
234 | -- "foo.bar.baz"; "bla/init.lua" returns "bla"; "foo.so" returns "foo". | ||
235 | -- @param file string: Pathname of module | ||
236 | -- @return string: The module identifier, or nil if given path is | ||
237 | -- not a conformant module path (the function does not check if the | ||
238 | -- path actually exists). | ||
239 | function path.path_to_module(file) | ||
240 | assert(type(file) == "string") | ||
241 | |||
242 | local name = file:match("(.*)%."..cfg.lua_extension.."$") | ||
243 | if name then | ||
244 | name = name:gsub(dir.separator, ".") | ||
245 | local init = name:match("(.*)%.init$") | ||
246 | if init then | ||
247 | name = init | ||
248 | end | ||
249 | else | ||
250 | name = file:match("(.*)%."..cfg.lib_extension.."$") | ||
251 | if name then | ||
252 | name = name:gsub(dir.separator, ".") | ||
253 | end | ||
254 | end | ||
255 | if not name then name = file end | ||
256 | name = name:gsub("^%.+", ""):gsub("%.+$", "") | ||
257 | return name | ||
258 | end | ||
259 | |||
260 | --- Obtain the directory name where a module should be stored. | 197 | --- Obtain the directory name where a module should be stored. |
261 | -- For example, on Unix, "foo.bar.baz" will return "foo/bar". | 198 | -- For example, on Unix, "foo.bar.baz" will return "foo/bar". |
262 | -- @param mod string: A module name in Lua dot-separated format. | 199 | -- @param mod string: A module name in Lua dot-separated format. |
@@ -286,22 +223,6 @@ function path.configure_paths(rockspec) | |||
286 | rockspec.variables = vars | 223 | rockspec.variables = vars |
287 | end | 224 | end |
288 | 225 | ||
289 | --- Produce a versioned version of a filename. | ||
290 | -- @param file string: filename (must start with prefix) | ||
291 | -- @param prefix string: Path prefix for file | ||
292 | -- @param name string: Rock name | ||
293 | -- @param version string: Rock version | ||
294 | -- @return string: a pathname with the same directory parts and a versioned basename. | ||
295 | function path.versioned_name(file, prefix, name, version) | ||
296 | assert(type(file) == "string") | ||
297 | assert(type(name) == "string") | ||
298 | assert(type(version) == "string") | ||
299 | |||
300 | local rest = file:sub(#prefix+1):gsub("^/*", "") | ||
301 | local name_version = (name.."_"..version):gsub("%-", "_"):gsub("%.", "_") | ||
302 | return dir.path(prefix, name_version.."-"..rest) | ||
303 | end | ||
304 | |||
305 | function path.use_tree(tree) | 226 | function path.use_tree(tree) |
306 | cfg.root_dir = tree | 227 | cfg.root_dir = tree |
307 | cfg.rocks_dir = path.rocks_dir(tree) | 228 | cfg.rocks_dir = path.rocks_dir(tree) |
@@ -310,6 +231,15 @@ function path.use_tree(tree) | |||
310 | cfg.deploy_lib_dir = path.deploy_lib_dir(tree) | 231 | cfg.deploy_lib_dir = path.deploy_lib_dir(tree) |
311 | end | 232 | end |
312 | 233 | ||
234 | function path.rocks_tree_to_string(tree) | ||
235 | if type(tree) == "string" then | ||
236 | return tree | ||
237 | else | ||
238 | assert(type(tree) == "table") | ||
239 | return tree.root | ||
240 | end | ||
241 | end | ||
242 | |||
313 | --- Apply a given function to the active rocks trees based on chosen dependency mode. | 243 | --- Apply a given function to the active rocks trees based on chosen dependency mode. |
314 | -- @param deps_mode string: Dependency mode: "one" for the current default tree, | 244 | -- @param deps_mode string: Dependency mode: "one" for the current default tree, |
315 | -- "all" for all trees, "order" for all trees with priority >= the current default, | 245 | -- "all" for all trees, "order" for all trees with priority >= the current default, |
@@ -338,51 +268,4 @@ function path.map_trees(deps_mode, fn, ...) | |||
338 | return result | 268 | return result |
339 | end | 269 | end |
340 | 270 | ||
341 | local is_src_extension = { [".lua"] = true, [".tl"] = true, [".tld"] = true, [".moon"] = true } | ||
342 | |||
343 | --- Return the pathname of the file that would be loaded for a module, indexed. | ||
344 | -- @param file_name string: module file name as in manifest (eg. "socket/core.so") | ||
345 | -- @param name string: name of the package (eg. "luasocket") | ||
346 | -- @param version string: version number (eg. "2.0.2-1") | ||
347 | -- @param tree string: repository path (eg. "/usr/local") | ||
348 | -- @param i number: the index, 1 if version is the current default, > 1 otherwise. | ||
349 | -- This is done this way for use by select_module in luarocks.loader. | ||
350 | -- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so") | ||
351 | function path.which_i(file_name, name, version, tree, i) | ||
352 | local deploy_dir | ||
353 | local extension = file_name:match("%.[a-z]+$") | ||
354 | if is_src_extension[extension] then | ||
355 | deploy_dir = path.deploy_lua_dir(tree) | ||
356 | file_name = dir.path(deploy_dir, file_name) | ||
357 | else | ||
358 | deploy_dir = path.deploy_lib_dir(tree) | ||
359 | file_name = dir.path(deploy_dir, file_name) | ||
360 | end | ||
361 | if i > 1 then | ||
362 | file_name = path.versioned_name(file_name, deploy_dir, name, version) | ||
363 | end | ||
364 | return file_name | ||
365 | end | ||
366 | |||
367 | --- Return the pathname of the file that would be loaded for a module, | ||
368 | -- returning the versioned pathname if given version is not the default version | ||
369 | -- in the given manifest. | ||
370 | -- @param module_name string: module name (eg. "socket.core") | ||
371 | -- @param file_name string: module file name as in manifest (eg. "socket/core.so") | ||
372 | -- @param name string: name of the package (eg. "luasocket") | ||
373 | -- @param version string: version number (eg. "2.0.2-1") | ||
374 | -- @param tree string: repository path (eg. "/usr/local") | ||
375 | -- @param manifest table: the manifest table for the tree. | ||
376 | -- @return string: filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so") | ||
377 | function path.which(module_name, file_name, name, version, tree, manifest) | ||
378 | local versions = manifest.modules[module_name] | ||
379 | assert(versions) | ||
380 | for i, name_version in ipairs(versions) do | ||
381 | if name_version == name.."/"..version then | ||
382 | return path.which_i(file_name, name, version, tree, i):gsub("//", "/") | ||
383 | end | ||
384 | end | ||
385 | assert(false) | ||
386 | end | ||
387 | |||
388 | return path | 271 | return path |
diff --git a/src/luarocks/persist.lua b/src/luarocks/persist.lua index 708f07be..6d5e917b 100644 --- a/src/luarocks/persist.lua +++ b/src/luarocks/persist.lua | |||
@@ -4,83 +4,10 @@ | |||
4 | -- Implemented separately to avoid interdependencies, | 4 | -- Implemented separately to avoid interdependencies, |
5 | -- as it is used in the bootstrapping stage of the cfg module. | 5 | -- as it is used in the bootstrapping stage of the cfg module. |
6 | local persist = {} | 6 | local persist = {} |
7 | package.loaded["luarocks.persist"] = persist | 7 | setmetatable(persist, { __index = require("luarocks.core.persist") }) |
8 | 8 | ||
9 | local util = require("luarocks.util") | 9 | local util = require("luarocks.util") |
10 | 10 | ||
11 | --- Load and run a Lua file in an environment. | ||
12 | -- @param filename string: the name of the file. | ||
13 | -- @param env table: the environment table. | ||
14 | -- @return (true, any) or (nil, string, string): true and the return value | ||
15 | -- of the file, or nil, an error message and an error code ("open", "load" | ||
16 | -- or "run") in case of errors. | ||
17 | local function run_file(filename, env) | ||
18 | local fd, err = io.open(filename) | ||
19 | if not fd then | ||
20 | return nil, err, "open" | ||
21 | end | ||
22 | local str, err = fd:read("*a") | ||
23 | fd:close() | ||
24 | if not str then | ||
25 | return nil, err, "open" | ||
26 | end | ||
27 | str = str:gsub("^#![^\n]*\n", "") | ||
28 | local chunk, ran | ||
29 | if _VERSION == "Lua 5.1" then -- Lua 5.1 | ||
30 | chunk, err = loadstring(str, filename) | ||
31 | if chunk then | ||
32 | setfenv(chunk, env) | ||
33 | ran, err = pcall(chunk) | ||
34 | end | ||
35 | else -- Lua 5.2 | ||
36 | chunk, err = load(str, filename, "t", env) | ||
37 | if chunk then | ||
38 | ran, err = pcall(chunk) | ||
39 | end | ||
40 | end | ||
41 | if not chunk then | ||
42 | return nil, "Error loading file: "..err, "load" | ||
43 | end | ||
44 | if not ran then | ||
45 | return nil, "Error running file: "..err, "run" | ||
46 | end | ||
47 | return true, err | ||
48 | end | ||
49 | |||
50 | --- Load a Lua file containing assignments, storing them in a table. | ||
51 | -- The global environment is not propagated to the loaded file. | ||
52 | -- @param filename string: the name of the file. | ||
53 | -- @param tbl table or nil: if given, this table is used to store | ||
54 | -- loaded values. | ||
55 | -- @return (table, table) or (nil, string, string): a table with the file's assignments | ||
56 | -- as fields and set of undefined globals accessed in file, | ||
57 | -- or nil, an error message and an error code ("open"; couldn't open the file, | ||
58 | -- "load"; compile-time error, or "run"; run-time error) | ||
59 | -- in case of errors. | ||
60 | function persist.load_into_table(filename, tbl) | ||
61 | assert(type(filename) == "string") | ||
62 | assert(type(tbl) == "table" or not tbl) | ||
63 | |||
64 | local result = tbl or {} | ||
65 | local globals = {} | ||
66 | local globals_mt = { | ||
67 | __index = function(t, k) | ||
68 | globals[k] = true | ||
69 | end | ||
70 | } | ||
71 | local save_mt = getmetatable(result) | ||
72 | setmetatable(result, globals_mt) | ||
73 | |||
74 | local ok, err, errcode = run_file(filename, result) | ||
75 | |||
76 | setmetatable(result, save_mt) | ||
77 | |||
78 | if not ok then | ||
79 | return nil, err, errcode | ||
80 | end | ||
81 | return result, globals | ||
82 | end | ||
83 | |||
84 | local write_table | 11 | local write_table |
85 | 12 | ||
86 | --- Write a value as Lua code. | 13 | --- Write a value as Lua code. |
diff --git a/src/luarocks/remove.lua b/src/luarocks/remove.lua index 514c6dfa..6cc8334f 100644 --- a/src/luarocks/remove.lua +++ b/src/luarocks/remove.lua | |||
@@ -1,8 +1,4 @@ | |||
1 | |||
2 | --- Module implementing the LuaRocks "remove" command. | ||
3 | -- Uninstalls rocks. | ||
4 | local remove = {} | 1 | local remove = {} |
5 | package.loaded["luarocks.remove"] = remove | ||
6 | 2 | ||
7 | local search = require("luarocks.search") | 3 | local search = require("luarocks.search") |
8 | local deps = require("luarocks.deps") | 4 | local deps = require("luarocks.deps") |
@@ -10,22 +6,7 @@ local fetch = require("luarocks.fetch") | |||
10 | local repos = require("luarocks.repos") | 6 | local repos = require("luarocks.repos") |
11 | local path = require("luarocks.path") | 7 | local path = require("luarocks.path") |
12 | local util = require("luarocks.util") | 8 | local util = require("luarocks.util") |
13 | local cfg = require("luarocks.cfg") | 9 | local cfg = require("luarocks.core.cfg") |
14 | local fs = require("luarocks.fs") | ||
15 | local manif = require("luarocks.manif") | ||
16 | |||
17 | util.add_run_function(remove) | ||
18 | remove.help_summary = "Uninstall a rock." | ||
19 | remove.help_arguments = "[--force|--force-fast] <name> [<version>]" | ||
20 | remove.help = [[ | ||
21 | Argument is the name of a rock to be uninstalled. | ||
22 | If a version is not given, try to remove all versions at once. | ||
23 | Will only perform the removal if it does not break dependencies. | ||
24 | To override this check and force the removal, use --force. | ||
25 | To perform a forced removal without reporting dependency issues, | ||
26 | use --force-fast. | ||
27 | |||
28 | ]]..util.deps_mode_help() | ||
29 | 10 | ||
30 | --- Obtain a list of packages that depend on the given set of packages | 11 | --- Obtain a list of packages that depend on the given set of packages |
31 | -- (where all packages of the set are versions of one program). | 12 | -- (where all packages of the set are versions of one program). |
@@ -131,44 +112,4 @@ function remove.remove_other_versions(name, version, force, fast) | |||
131 | return true | 112 | return true |
132 | end | 113 | end |
133 | 114 | ||
134 | --- Driver function for the "remove" command. | ||
135 | -- @param name string: name of a rock. If a version is given, refer to | ||
136 | -- a specific version; otherwise, try to remove all versions. | ||
137 | -- @param version string: When passing a package name, a version number | ||
138 | -- may also be given. | ||
139 | -- @return boolean or (nil, string, exitcode): True if removal was | ||
140 | -- successful, nil and an error message otherwise. exitcode is optionally returned. | ||
141 | function remove.command(flags, name, version) | ||
142 | if type(name) ~= "string" then | ||
143 | return nil, "Argument missing. "..util.see_help("remove") | ||
144 | end | ||
145 | |||
146 | local deps_mode = flags["deps-mode"] or cfg.deps_mode | ||
147 | |||
148 | local ok, err = fs.check_command_permissions(flags) | ||
149 | if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end | ||
150 | |||
151 | local rock_type = name:match("%.(rock)$") or name:match("%.(rockspec)$") | ||
152 | local filename = name | ||
153 | if rock_type then | ||
154 | name, version = path.parse_name(filename) | ||
155 | if not name then return nil, "Invalid "..rock_type.." filename: "..filename end | ||
156 | end | ||
157 | |||
158 | local results = {} | ||
159 | name = name:lower() | ||
160 | search.manifest_search(results, cfg.rocks_dir, search.make_query(name, version)) | ||
161 | if not results[name] then | ||
162 | return nil, "Could not find rock '"..name..(version and " "..version or "").."' in "..path.rocks_tree_to_string(cfg.root_dir) | ||
163 | end | ||
164 | |||
165 | local ok, err = remove.remove_search_results(results, name, deps_mode, flags["force"], flags["force-fast"]) | ||
166 | if not ok then | ||
167 | return nil, err | ||
168 | end | ||
169 | |||
170 | manif.check_dependencies(nil, deps.get_deps_mode(flags)) | ||
171 | return true | ||
172 | end | ||
173 | |||
174 | return remove | 115 | return remove |
diff --git a/src/luarocks/repos.lua b/src/luarocks/repos.lua index abc62b0d..1abb5628 100644 --- a/src/luarocks/repos.lua +++ b/src/luarocks/repos.lua | |||
@@ -1,15 +1,14 @@ | |||
1 | 1 | ||
2 | --- Functions for managing the repository on disk. | 2 | --- Functions for managing the repository on disk. |
3 | local repos = {} | 3 | local repos = {} |
4 | package.loaded["luarocks.repos"] = repos | ||
5 | 4 | ||
6 | local fs = require("luarocks.fs") | 5 | local fs = require("luarocks.fs") |
7 | local path = require("luarocks.path") | 6 | local path = require("luarocks.path") |
8 | local cfg = require("luarocks.cfg") | 7 | local cfg = require("luarocks.core.cfg") |
9 | local util = require("luarocks.util") | 8 | local util = require("luarocks.util") |
10 | local dir = require("luarocks.dir") | 9 | local dir = require("luarocks.dir") |
11 | local manif = require("luarocks.manif") | 10 | local manif = require("luarocks.manif") |
12 | local deps = require("luarocks.deps") | 11 | local vers = require("luarocks.vers") |
13 | 12 | ||
14 | -- Tree of files installed by a package are stored | 13 | -- Tree of files installed by a package are stored |
15 | -- in its rock manifest. Some of these files have to | 14 | -- in its rock manifest. Some of these files have to |
@@ -55,67 +54,73 @@ end | |||
55 | local function recurse_rock_manifest_tree(file_tree, action) | 54 | local function recurse_rock_manifest_tree(file_tree, action) |
56 | assert(type(file_tree) == "table") | 55 | assert(type(file_tree) == "table") |
57 | assert(type(action) == "function") | 56 | assert(type(action) == "function") |
58 | local function do_recurse_rock_manifest_tree(tree, parent_path, parent_module) | 57 | |
59 | 58 | local function do_recurse_rock_manifest_tree(tree, parent_path) | |
60 | for file, sub in pairs(tree) do | 59 | for file, sub in pairs(tree) do |
60 | local sub_path = (parent_path and (parent_path .. "/") or "") .. file | ||
61 | local ok, err | ||
62 | |||
61 | if type(sub) == "table" then | 63 | if type(sub) == "table" then |
62 | local ok, err = do_recurse_rock_manifest_tree(sub, parent_path..file.."/", parent_module..file..".") | 64 | ok, err = do_recurse_rock_manifest_tree(sub, sub_path) |
63 | if not ok then return nil, err end | ||
64 | else | 65 | else |
65 | local ok, err = action(parent_path, parent_module, file) | 66 | ok, err = action(sub_path) |
66 | if not ok then return nil, err end | ||
67 | end | 67 | end |
68 | |||
69 | if not ok then return nil, err end | ||
68 | end | 70 | end |
69 | return true | 71 | return true |
70 | end | 72 | end |
71 | return do_recurse_rock_manifest_tree(file_tree, "", "") | 73 | return do_recurse_rock_manifest_tree(file_tree) |
72 | end | 74 | end |
73 | 75 | ||
74 | local function store_package_data(result, name, file_tree) | 76 | local function store_package_data(result, rock_manifest, deploy_type) |
75 | if not file_tree then return end | 77 | if rock_manifest[deploy_type] then |
76 | return recurse_rock_manifest_tree(file_tree, | 78 | recurse_rock_manifest_tree(rock_manifest[deploy_type], function(file_path) |
77 | function(parent_path, parent_module, file) | 79 | local _, item_name = manif.get_provided_item(deploy_type, file_path) |
78 | local pathname = parent_path..file | 80 | result[item_name] = file_path |
79 | result[path.path_to_module(pathname)] = pathname | ||
80 | return true | 81 | return true |
81 | end | 82 | end) |
82 | ) | 83 | end |
83 | end | 84 | end |
84 | 85 | ||
85 | --- Obtain a list of modules within an installed package. | 86 | --- Obtain a table of modules within an installed package. |
86 | -- @param package string: The package name; for example "luasocket" | 87 | -- @param name string: The package name; for example "luasocket" |
87 | -- @param version string: The exact version number including revision; | 88 | -- @param version string: The exact version number including revision; |
88 | -- for example "2.0.1-1". | 89 | -- for example "2.0.1-1". |
89 | -- @return table: A table of modules where keys are module identifiers | 90 | -- @return table: A table of modules where keys are module names |
90 | -- in "foo.bar" format and values are pathnames in architecture-dependent | 91 | -- and values are file paths of files providing modules |
91 | -- "foo/bar.so" format. If no modules are found or if package or version | 92 | -- relative to "lib" or "lua" rock manifest subtree. |
93 | -- If no modules are found or if package name or version | ||
92 | -- are invalid, an empty table is returned. | 94 | -- are invalid, an empty table is returned. |
93 | function repos.package_modules(package, version) | 95 | function repos.package_modules(name, version) |
94 | assert(type(package) == "string") | 96 | assert(type(name) == "string") |
95 | assert(type(version) == "string") | 97 | assert(type(version) == "string") |
96 | 98 | ||
97 | local result = {} | 99 | local result = {} |
98 | local rock_manifest = manif.load_rock_manifest(package, version) | 100 | local rock_manifest = manif.load_rock_manifest(name, version) |
99 | store_package_data(result, package, rock_manifest.lib) | 101 | if not rock_manifest then return result end |
100 | store_package_data(result, package, rock_manifest.lua) | 102 | store_package_data(result, rock_manifest, "lib") |
103 | store_package_data(result, rock_manifest, "lua") | ||
101 | return result | 104 | return result |
102 | end | 105 | end |
103 | 106 | ||
104 | --- Obtain a list of command-line scripts within an installed package. | 107 | --- Obtain a table of command-line scripts within an installed package. |
105 | -- @param package string: The package name; for example "luasocket" | 108 | -- @param name string: The package name; for example "luasocket" |
106 | -- @param version string: The exact version number including revision; | 109 | -- @param version string: The exact version number including revision; |
107 | -- for example "2.0.1-1". | 110 | -- for example "2.0.1-1". |
108 | -- @return table: A table of items where keys are command names | 111 | -- @return table: A table of commands where keys and values are command names |
109 | -- as strings and values are pathnames in architecture-dependent | 112 | -- as strings - file paths of files providing commands |
110 | -- ".../bin/foo" format. If no modules are found or if package or version | 113 | -- relative to "bin" rock manifest subtree. |
114 | -- If no commands are found or if package name or version | ||
111 | -- are invalid, an empty table is returned. | 115 | -- are invalid, an empty table is returned. |
112 | function repos.package_commands(package, version) | 116 | function repos.package_commands(name, version) |
113 | assert(type(package) == "string") | 117 | assert(type(name) == "string") |
114 | assert(type(version) == "string") | 118 | assert(type(version) == "string") |
115 | 119 | ||
116 | local result = {} | 120 | local result = {} |
117 | local rock_manifest = manif.load_rock_manifest(package, version) | 121 | local rock_manifest = manif.load_rock_manifest(name, version) |
118 | store_package_data(result, package, rock_manifest.bin) | 122 | if not rock_manifest then return result end |
123 | store_package_data(result, rock_manifest, "bin") | ||
119 | return result | 124 | return result |
120 | end | 125 | end |
121 | 126 | ||
@@ -130,7 +135,7 @@ function repos.has_binaries(name, version) | |||
130 | assert(type(version) == "string") | 135 | assert(type(version) == "string") |
131 | 136 | ||
132 | local rock_manifest = manif.load_rock_manifest(name, version) | 137 | local rock_manifest = manif.load_rock_manifest(name, version) |
133 | if rock_manifest.bin then | 138 | if rock_manifest and rock_manifest.bin then |
134 | for name, md5 in pairs(rock_manifest.bin) do | 139 | for name, md5 in pairs(rock_manifest.bin) do |
135 | -- TODO verify that it is the same file. If it isn't, find the actual command. | 140 | -- TODO verify that it is the same file. If it isn't, find the actual command. |
136 | if fs.is_actual_binary(dir.path(cfg.deploy_bin_dir, name)) then | 141 | if fs.is_actual_binary(dir.path(cfg.deploy_bin_dir, name)) then |
@@ -241,7 +246,7 @@ local function prepare_target(name, version, deploy_type, file_path, suffix) | |||
241 | 246 | ||
242 | if not cur_name then | 247 | if not cur_name then |
243 | return non_versioned | 248 | return non_versioned |
244 | elseif name < cur_name or (name == cur_name and deps.compare_versions(version, cur_version)) then | 249 | elseif name < cur_name or (name == cur_name and vers.compare_versions(version, cur_version)) then |
245 | -- New version has priority. Move currently provided version back using versioned name. | 250 | -- New version has priority. Move currently provided version back using versioned name. |
246 | local cur_deploy_type, cur_file_path = manif.get_providing_file(cur_name, cur_version, item_type, item_name) | 251 | local cur_deploy_type, cur_file_path = manif.get_providing_file(cur_name, cur_version, item_type, item_name) |
247 | local cur_non_versioned, cur_versioned = get_deploy_paths(cur_name, cur_version, cur_deploy_type, cur_file_path) | 252 | local cur_non_versioned, cur_versioned = get_deploy_paths(cur_name, cur_version, cur_deploy_type, cur_file_path) |
@@ -271,15 +276,15 @@ function repos.deploy_files(name, version, wrap_bin_scripts, deps_mode) | |||
271 | assert(type(version) == "string") | 276 | assert(type(version) == "string") |
272 | assert(type(wrap_bin_scripts) == "boolean") | 277 | assert(type(wrap_bin_scripts) == "boolean") |
273 | 278 | ||
274 | local rock_manifest = manif.load_rock_manifest(name, version) | 279 | local rock_manifest, load_err = manif.load_rock_manifest(name, version) |
280 | if not rock_manifest then return nil, load_err end | ||
275 | 281 | ||
276 | local function deploy_file_tree(deploy_type, source_dir, move_fn, suffix) | 282 | local function deploy_file_tree(deploy_type, source_dir, move_fn, suffix) |
277 | if not rock_manifest[deploy_type] then | 283 | if not rock_manifest[deploy_type] then |
278 | return true | 284 | return true |
279 | end | 285 | end |
280 | 286 | ||
281 | return recurse_rock_manifest_tree(rock_manifest[deploy_type], function(parent_path, parent_module, file) | 287 | return recurse_rock_manifest_tree(rock_manifest[deploy_type], function(file_path) |
282 | local file_path = parent_path .. file | ||
283 | local source = dir.path(source_dir, file_path) | 288 | local source = dir.path(source_dir, file_path) |
284 | 289 | ||
285 | local target, prepare_err = prepare_target(name, version, deploy_type, file_path, suffix) | 290 | local target, prepare_err = prepare_target(name, version, deploy_type, file_path, suffix) |
@@ -331,7 +336,8 @@ function repos.deploy_files(name, version, wrap_bin_scripts, deps_mode) | |||
331 | ok, err = deploy_file_tree("lib", path.lib_dir(name, version), make_mover(cfg.perm_exec)) | 336 | ok, err = deploy_file_tree("lib", path.lib_dir(name, version), make_mover(cfg.perm_exec)) |
332 | if not ok then return nil, err end | 337 | if not ok then return nil, err end |
333 | 338 | ||
334 | return manif.add_to_manifest(name, version, nil, deps_mode) | 339 | local writer = require("luarocks.manif.writer") |
340 | return writer.add_to_manifest(name, version, nil, deps_mode) | ||
335 | end | 341 | end |
336 | 342 | ||
337 | --- Delete a package from the local repository. | 343 | --- Delete a package from the local repository. |
@@ -349,18 +355,15 @@ function repos.delete_version(name, version, deps_mode, quick) | |||
349 | assert(type(version) == "string") | 355 | assert(type(version) == "string") |
350 | assert(type(deps_mode) == "string") | 356 | assert(type(deps_mode) == "string") |
351 | 357 | ||
352 | local rock_manifest = manif.load_rock_manifest(name, version) | 358 | local rock_manifest, load_err = manif.load_rock_manifest(name, version) |
353 | if not rock_manifest then | 359 | if not rock_manifest then return nil, load_err end |
354 | return nil, "rock_manifest file not found for "..name.." "..version.." - not a LuaRocks 2 tree?" | ||
355 | end | ||
356 | 360 | ||
357 | local function delete_deployed_file_tree(deploy_type, suffix) | 361 | local function delete_deployed_file_tree(deploy_type, suffix) |
358 | if not rock_manifest[deploy_type] then | 362 | if not rock_manifest[deploy_type] then |
359 | return true | 363 | return true |
360 | end | 364 | end |
361 | 365 | ||
362 | return recurse_rock_manifest_tree(rock_manifest[deploy_type], function(parent_path, parent_module, file) | 366 | return recurse_rock_manifest_tree(rock_manifest[deploy_type], function(file_path) |
363 | local file_path = parent_path .. file | ||
364 | local non_versioned, versioned = get_deploy_paths(name, version, deploy_type, file_path) | 367 | local non_versioned, versioned = get_deploy_paths(name, version, deploy_type, file_path) |
365 | 368 | ||
366 | -- Figure out if the file is deployed using versioned or non-versioned name. | 369 | -- Figure out if the file is deployed using versioned or non-versioned name. |
@@ -417,7 +420,30 @@ function repos.delete_version(name, version, deps_mode, quick) | |||
417 | return true | 420 | return true |
418 | end | 421 | end |
419 | 422 | ||
420 | return manif.remove_from_manifest(name, version, nil, deps_mode) | 423 | local writer = require("luarocks.manif.writer") |
424 | return writer.remove_from_manifest(name, version, nil, deps_mode) | ||
425 | end | ||
426 | |||
427 | --- Find full path to a file providing a module or a command | ||
428 | -- in a package. | ||
429 | -- @param name string: name of package. | ||
430 | -- @param version string: exact package version in string format. | ||
431 | -- @param item_type string: "module" or "command". | ||
432 | -- @param item_name string: module or command name. | ||
433 | -- @param root string or nil: A local root dir for a rocks tree. If not given, the default is used. | ||
434 | -- @return string: absolute path to the file providing given module | ||
435 | -- or command. | ||
436 | function repos.which(name, version, item_type, item_name, repo) | ||
437 | local deploy_type, file_path = manif.get_providing_file(name, version, item_type, item_name, repo) | ||
438 | local non_versioned, versioned = get_deploy_paths(name, version, deploy_type, file_path, repo) | ||
439 | local cur_name, cur_version = manif.get_current_provider(item_type, item_name) | ||
440 | local deploy_path = (name == cur_name and version == cur_version) and non_versioned or versioned | ||
441 | |||
442 | if deploy_type == "bin" and cfg.wrapper_suffix and cfg.wrapper_suffix ~= "" then | ||
443 | deploy_path = find_suffixed(deploy_path, cfg.wrapper_suffix) or deploy_path | ||
444 | end | ||
445 | |||
446 | return deploy_path | ||
421 | end | 447 | end |
422 | 448 | ||
423 | --- Find full path to a file providing a module or a command | 449 | --- Find full path to a file providing a module or a command |
diff --git a/src/luarocks/search.lua b/src/luarocks/search.lua index d22c2a18..35010c2b 100644 --- a/src/luarocks/search.lua +++ b/src/luarocks/search.lua | |||
@@ -1,28 +1,12 @@ | |||
1 | |||
2 | --- Module implementing the LuaRocks "search" command. | ||
3 | -- Queries LuaRocks servers. | ||
4 | local search = {} | 1 | local search = {} |
5 | package.loaded["luarocks.search"] = search | ||
6 | 2 | ||
7 | local dir = require("luarocks.dir") | 3 | local dir = require("luarocks.dir") |
8 | local path = require("luarocks.path") | 4 | local path = require("luarocks.path") |
9 | local manif = require("luarocks.manif") | 5 | local manif = require("luarocks.manif") |
10 | local deps = require("luarocks.deps") | 6 | local vers = require("luarocks.vers") |
11 | local cfg = require("luarocks.cfg") | 7 | local cfg = require("luarocks.core.cfg") |
12 | local util = require("luarocks.util") | 8 | local util = require("luarocks.util") |
13 | 9 | ||
14 | util.add_run_function(search) | ||
15 | search.help_summary = "Query the LuaRocks servers." | ||
16 | search.help_arguments = "[--source] [--binary] { <name> [<version>] | --all }" | ||
17 | search.help = [[ | ||
18 | --source Return only rockspecs and source rocks, | ||
19 | to be used with the "build" command. | ||
20 | --binary Return only pure Lua and binary rocks (rocks that can be used | ||
21 | with the "install" command without requiring a C toolchain). | ||
22 | --all List all contents of the server that are suitable to | ||
23 | this platform, do not filter by name. | ||
24 | ]] | ||
25 | |||
26 | --- Convert the arch field of a query table to table format. | 10 | --- Convert the arch field of a query table to table format. |
27 | -- @param query table: A query table. | 11 | -- @param query table: A query table. |
28 | local function query_arch_as_table(query) | 12 | local function query_arch_as_table(query) |
@@ -56,7 +40,7 @@ end | |||
56 | -- identifier), "rockspec" or "installed" | 40 | -- identifier), "rockspec" or "installed" |
57 | -- @param repo string: Pathname of a local repository of URL of | 41 | -- @param repo string: Pathname of a local repository of URL of |
58 | -- rocks server. | 42 | -- rocks server. |
59 | local function store_result(results, name, version, arch, repo) | 43 | function search.store_result(results, name, version, arch, repo) |
60 | assert(type(results) == "table") | 44 | assert(type(results) == "table") |
61 | assert(type(name) == "string") | 45 | assert(type(name) == "string") |
62 | assert(type(version) == "string") | 46 | assert(type(version) == "string") |
@@ -108,8 +92,8 @@ end | |||
108 | local function store_if_match(results, repo, name, version, arch, query) | 92 | local function store_if_match(results, repo, name, version, arch, query) |
109 | if match_name(query, name) then | 93 | if match_name(query, name) then |
110 | if query.arch[arch] or query.arch["any"] then | 94 | if query.arch[arch] or query.arch["any"] then |
111 | if deps.match_constraints(deps.parse_version(version), query.constraints) then | 95 | if vers.match_constraints(vers.parse_version(version), query.constraints) then |
112 | store_result(results, name, version, arch, repo) | 96 | search.store_result(results, name, version, arch, repo) |
113 | end | 97 | end |
114 | end | 98 | end |
115 | end | 99 | end |
@@ -245,7 +229,7 @@ function search.make_query(name, version) | |||
245 | constraints = {} | 229 | constraints = {} |
246 | } | 230 | } |
247 | if version then | 231 | if version then |
248 | table.insert(query.constraints, { op = "==", version = deps.parse_version(version)}) | 232 | table.insert(query.constraints, { op = "==", version = vers.parse_version(version)}) |
249 | end | 233 | end |
250 | return query | 234 | return query |
251 | end | 235 | end |
@@ -262,7 +246,7 @@ local function pick_latest_version(name, versions) | |||
262 | 246 | ||
263 | local vtables = {} | 247 | local vtables = {} |
264 | for v, _ in pairs(versions) do | 248 | for v, _ in pairs(versions) do |
265 | table.insert(vtables, deps.parse_version(v)) | 249 | table.insert(vtables, vers.parse_version(v)) |
266 | end | 250 | end |
267 | table.sort(vtables) | 251 | table.sort(vtables) |
268 | local version = vtables[#vtables].string | 252 | local version = vtables[#vtables].string |
@@ -355,7 +339,7 @@ function search.print_results(results, porcelain) | |||
355 | if not porcelain then | 339 | if not porcelain then |
356 | util.printout(package) | 340 | util.printout(package) |
357 | end | 341 | end |
358 | for version, repos in util.sortedpairs(versions, deps.compare_versions) do | 342 | for version, repos in util.sortedpairs(versions, vers.compare_versions) do |
359 | for _, repo in ipairs(repos) do | 343 | for _, repo in ipairs(repos) do |
360 | repo.repo = dir.normalize(repo.repo) | 344 | repo.repo = dir.normalize(repo.repo) |
361 | if porcelain then | 345 | if porcelain then |
@@ -371,28 +355,6 @@ function search.print_results(results, porcelain) | |||
371 | end | 355 | end |
372 | end | 356 | end |
373 | 357 | ||
374 | --- Splits a list of search results into two lists, one for "source" results | ||
375 | -- to be used with the "build" command, and one for "binary" results to be | ||
376 | -- used with the "install" command. | ||
377 | -- @param results table: A search results table. | ||
378 | -- @return (table, table): Two tables, one for source and one for binary | ||
379 | -- results. | ||
380 | local function split_source_and_binary_results(results) | ||
381 | local sources, binaries = {}, {} | ||
382 | for name, versions in pairs(results) do | ||
383 | for version, repositories in pairs(versions) do | ||
384 | for _, repo in ipairs(repositories) do | ||
385 | local where = sources | ||
386 | if repo.arch == "all" or repo.arch == cfg.arch then | ||
387 | where = binaries | ||
388 | end | ||
389 | store_result(where, name, version, repo.arch, repo.repo) | ||
390 | end | ||
391 | end | ||
392 | end | ||
393 | return sources, binaries | ||
394 | end | ||
395 | |||
396 | --- Given a name and optionally a version, try to find in the rocks | 358 | --- Given a name and optionally a version, try to find in the rocks |
397 | -- servers a single .src.rock or .rockspec file that satisfies | 359 | -- servers a single .src.rock or .rockspec file that satisfies |
398 | -- the request, and run the given function on it; or display to the | 360 | -- the request, and run the given function on it; or display to the |
@@ -440,7 +402,7 @@ function search.pick_installed_rock(name, version, given_tree) | |||
440 | local package, versions = util.sortedpairs(results)() | 402 | local package, versions = util.sortedpairs(results)() |
441 | --question: what do we do about multiple versions? This should | 403 | --question: what do we do about multiple versions? This should |
442 | --give us the latest version on the last repo (which is usually the global one) | 404 | --give us the latest version on the last repo (which is usually the global one) |
443 | for vs, repositories in util.sortedpairs(versions, deps.compare_versions) do | 405 | for vs, repositories in util.sortedpairs(versions, vers.compare_versions) do |
444 | if not version then version = vs end | 406 | if not version then version = vs end |
445 | for _, rp in ipairs(repositories) do repo_url = rp.repo end | 407 | for _, rp in ipairs(repositories) do repo_url = rp.repo end |
446 | end | 408 | end |
@@ -449,35 +411,4 @@ function search.pick_installed_rock(name, version, given_tree) | |||
449 | return name, version, repo, repo_url | 411 | return name, version, repo, repo_url |
450 | end | 412 | end |
451 | 413 | ||
452 | --- Driver function for "search" command. | ||
453 | -- @param name string: A substring of a rock name to search. | ||
454 | -- @param version string or nil: a version may also be passed. | ||
455 | -- @return boolean or (nil, string): True if build was successful; nil and an | ||
456 | -- error message otherwise. | ||
457 | function search.command(flags, name, version) | ||
458 | if flags["all"] then | ||
459 | name, version = "", nil | ||
460 | end | ||
461 | |||
462 | if type(name) ~= "string" and not flags["all"] then | ||
463 | return nil, "Enter name and version or use --all. "..util.see_help("search") | ||
464 | end | ||
465 | |||
466 | local query = search.make_query(name:lower(), version) | ||
467 | query.exact_name = false | ||
468 | local results, err = search.search_repos(query) | ||
469 | local porcelain = flags["porcelain"] | ||
470 | util.title("Search results:", porcelain, "=") | ||
471 | local sources, binaries = split_source_and_binary_results(results) | ||
472 | if next(sources) and not flags["binary"] then | ||
473 | util.title("Rockspecs and source rocks:", porcelain) | ||
474 | search.print_results(sources, porcelain) | ||
475 | end | ||
476 | if next(binaries) and not flags["source"] then | ||
477 | util.title("Binary and pure-Lua rocks:", porcelain) | ||
478 | search.print_results(binaries, porcelain) | ||
479 | end | ||
480 | return true | ||
481 | end | ||
482 | |||
483 | return search | 414 | return search |
diff --git a/src/luarocks/tools/tar.lua b/src/luarocks/tools/tar.lua index 637a6c95..ae5c83e2 100644 --- a/src/luarocks/tools/tar.lua +++ b/src/luarocks/tools/tar.lua | |||
@@ -56,10 +56,11 @@ end | |||
56 | local function read_header_block(block) | 56 | local function read_header_block(block) |
57 | local header = {} | 57 | local header = {} |
58 | header.name = nullterm(block:sub(1,100)) | 58 | header.name = nullterm(block:sub(1,100)) |
59 | header.mode = nullterm(block:sub(101,108)) | 59 | header.mode = nullterm(block:sub(101,108)):gsub(" ", "") |
60 | header.uid = octal_to_number(nullterm(block:sub(109,116))) | 60 | header.uid = octal_to_number(nullterm(block:sub(109,116))) |
61 | header.gid = octal_to_number(nullterm(block:sub(117,124))) | 61 | header.gid = octal_to_number(nullterm(block:sub(117,124))) |
62 | header.size = octal_to_number(nullterm(block:sub(125,136))) | 62 | header.size = octal_to_number(nullterm(block:sub(125,136))) |
63 | print("{"..block:sub(125,136).."}", "{"..nullterm(block:sub(125,136)).."}", "{"..octal_to_number(nullterm(block:sub(125,136))).."}", header.size) | ||
63 | header.mtime = octal_to_number(nullterm(block:sub(137,148))) | 64 | header.mtime = octal_to_number(nullterm(block:sub(137,148))) |
64 | header.chksum = octal_to_number(nullterm(block:sub(149,156))) | 65 | header.chksum = octal_to_number(nullterm(block:sub(149,156))) |
65 | header.typeflag = get_typeflag(block:sub(157,157)) | 66 | header.typeflag = get_typeflag(block:sub(157,157)) |
@@ -93,13 +94,14 @@ function tar.untar(filename, destdir) | |||
93 | local long_name, long_link_name | 94 | local long_name, long_link_name |
94 | while true do | 95 | while true do |
95 | local block | 96 | local block |
96 | repeat | 97 | repeat |
97 | block = tar_handle:read(blocksize) | 98 | block = tar_handle:read(blocksize) |
98 | until (not block) or checksum_header(block) > 256 | 99 | until (not block) or checksum_header(block) > 256 |
99 | if not block then break end | 100 | if not block then break end |
100 | local header, err = read_header_block(block) | 101 | local header, err = read_header_block(block) |
101 | if not header then | 102 | if not header then |
102 | util.printerr(err) | 103 | util.printerr(err) |
104 | return nil, err | ||
103 | end | 105 | end |
104 | 106 | ||
105 | local file_data = tar_handle:read(math.ceil(header.size / blocksize) * blocksize):sub(1,header.size) | 107 | local file_data = tar_handle:read(math.ceil(header.size / blocksize) * blocksize):sub(1,header.size) |
diff --git a/src/luarocks/type_check.lua b/src/luarocks/type_check.lua index 63c59ca2..4b7e68d7 100644 --- a/src/luarocks/type_check.lua +++ b/src/luarocks/type_check.lua | |||
@@ -2,16 +2,15 @@ | |||
2 | -- Functions and definitions for doing a basic lint check on files | 2 | -- Functions and definitions for doing a basic lint check on files |
3 | -- loaded by LuaRocks. | 3 | -- loaded by LuaRocks. |
4 | local type_check = {} | 4 | local type_check = {} |
5 | package.loaded["luarocks.type_check"] = type_check | 5 | setmetatable(type_check, { __index = require("luarocks.core.type_check") }) |
6 | 6 | ||
7 | local cfg = require("luarocks.cfg") | 7 | type_check.rockspec_format = "3.0" |
8 | local deps = require("luarocks.deps") | ||
9 | 8 | ||
10 | type_check.rockspec_format = "1.1" | 9 | local string_1 = type_check.string_1 |
10 | local mandatory_string_1 = type_check.mandatory_string_1 | ||
11 | 11 | ||
12 | local string_1 = { _type = "string" } | 12 | local string_3 = { _type = "string", _version = "3.0" } |
13 | local number_1 = { _type = "number" } | 13 | local list_of_strings_3 = { _any = string_3, _version = "3.0" } |
14 | local mandatory_string_1 = { _type = "string", _mandatory = true } | ||
15 | 14 | ||
16 | -- Syntax for type-checking tables: | 15 | -- Syntax for type-checking tables: |
17 | -- | 16 | -- |
@@ -37,6 +36,8 @@ local rockspec_types = { | |||
37 | homepage = string_1, | 36 | homepage = string_1, |
38 | license = string_1, | 37 | license = string_1, |
39 | maintainer = string_1, | 38 | maintainer = string_1, |
39 | labels = list_of_strings_3, | ||
40 | issues_url = string_3, | ||
40 | }, | 41 | }, |
41 | dependencies = { | 42 | dependencies = { |
42 | platforms = {}, -- recursively defined below | 43 | platforms = {}, -- recursively defined below |
@@ -112,206 +113,6 @@ rockspec_types.external_dependencies.platforms._any = rockspec_types.external_de | |||
112 | rockspec_types.source.platforms._any = rockspec_types.source | 113 | rockspec_types.source.platforms._any = rockspec_types.source |
113 | rockspec_types.hooks.platforms._any = rockspec_types.hooks | 114 | rockspec_types.hooks.platforms._any = rockspec_types.hooks |
114 | 115 | ||
115 | local manifest_types = { | ||
116 | repository = { | ||
117 | _mandatory = true, | ||
118 | -- packages | ||
119 | _any = { | ||
120 | -- versions | ||
121 | _any = { | ||
122 | -- items | ||
123 | _any = { | ||
124 | arch = mandatory_string_1, | ||
125 | modules = { _any = string_1 }, | ||
126 | commands = { _any = string_1 }, | ||
127 | dependencies = { _any = string_1 }, | ||
128 | -- TODO: to be extended with more metadata. | ||
129 | } | ||
130 | } | ||
131 | } | ||
132 | }, | ||
133 | modules = { | ||
134 | _mandatory = true, | ||
135 | -- modules | ||
136 | _any = { | ||
137 | -- providers | ||
138 | _any = string_1 | ||
139 | } | ||
140 | }, | ||
141 | commands = { | ||
142 | _mandatory = true, | ||
143 | -- modules | ||
144 | _any = { | ||
145 | -- commands | ||
146 | _any = string_1 | ||
147 | } | ||
148 | }, | ||
149 | dependencies = { | ||
150 | -- each module | ||
151 | _any = { | ||
152 | -- each version | ||
153 | _any = { | ||
154 | -- each dependency | ||
155 | _any = { | ||
156 | name = string_1, | ||
157 | constraints = { | ||
158 | _any = { | ||
159 | no_upgrade = { _type = "boolean" }, | ||
160 | op = string_1, | ||
161 | version = { | ||
162 | string = string_1, | ||
163 | _any = number_1, | ||
164 | } | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | } | ||
170 | } | ||
171 | } | ||
172 | |||
173 | local function check_version(version, typetbl, context) | ||
174 | local typetbl_version = typetbl._version or "1.0" | ||
175 | if deps.compare_versions(typetbl_version, version) then | ||
176 | if context == "" then | ||
177 | return nil, "Invalid rockspec_format version number in rockspec? Please fix rockspec accordingly." | ||
178 | else | ||
179 | return nil, context.." is not supported in rockspec format "..version.." (requires version "..typetbl_version.."), please fix the rockspec_format field accordingly." | ||
180 | end | ||
181 | end | ||
182 | return true | ||
183 | end | ||
184 | |||
185 | local type_check_table | ||
186 | |||
187 | --- Type check an object. | ||
188 | -- The object is compared against an archetypical value | ||
189 | -- matching the expected type -- the actual values don't matter, | ||
190 | -- only their types. Tables are type checked recursively. | ||
191 | -- @param version string: The version of the item. | ||
192 | -- @param item any: The object being checked. | ||
193 | -- @param typetbl any: The type-checking table for the object. | ||
194 | -- @param context string: A string indicating the "context" where the | ||
195 | -- error occurred (the full table path), for error messages. | ||
196 | -- @return boolean or (nil, string): true if type checking | ||
197 | -- succeeded, or nil and an error message if it failed. | ||
198 | -- @see type_check_table | ||
199 | local function type_check_item(version, item, typetbl, context) | ||
200 | assert(type(version) == "string") | ||
201 | |||
202 | local ok, err = check_version(version, typetbl, context) | ||
203 | if not ok then | ||
204 | return nil, err | ||
205 | end | ||
206 | |||
207 | local item_type = type(item) or "nil" | ||
208 | local expected_type = typetbl._type or "table" | ||
209 | |||
210 | if expected_type == "number" then | ||
211 | if not tonumber(item) then | ||
212 | return nil, "Type mismatch on field "..context..": expected a number" | ||
213 | end | ||
214 | elseif expected_type == "string" then | ||
215 | if item_type ~= "string" then | ||
216 | return nil, "Type mismatch on field "..context..": expected a string, got "..item_type | ||
217 | end | ||
218 | if typetbl._pattern then | ||
219 | if not item:match("^"..typetbl._pattern.."$") then | ||
220 | return nil, "Type mismatch on field "..context..": invalid value "..item.." does not match '"..typetbl._pattern.."'" | ||
221 | end | ||
222 | end | ||
223 | elseif expected_type == "table" then | ||
224 | if item_type ~= expected_type then | ||
225 | return nil, "Type mismatch on field "..context..": expected a table" | ||
226 | else | ||
227 | return type_check_table(version, item, typetbl, context) | ||
228 | end | ||
229 | elseif item_type ~= expected_type then | ||
230 | return nil, "Type mismatch on field "..context..": expected "..expected_type | ||
231 | end | ||
232 | return true | ||
233 | end | ||
234 | |||
235 | local function mkfield(context, field) | ||
236 | if context == "" then | ||
237 | return tostring(field) | ||
238 | elseif type(field) == "string" then | ||
239 | return context.."."..field | ||
240 | else | ||
241 | return context.."["..tostring(field).."]" | ||
242 | end | ||
243 | end | ||
244 | |||
245 | --- Type check the contents of a table. | ||
246 | -- The table's contents are compared against a reference table, | ||
247 | -- which contains the recognized fields, with archetypical values | ||
248 | -- matching the expected types -- the actual values of items in the | ||
249 | -- reference table don't matter, only their types (ie, for field x | ||
250 | -- in tbl that is correctly typed, type(tbl.x) == type(types.x)). | ||
251 | -- If the reference table contains a field called MORE, then | ||
252 | -- unknown fields in the checked table are accepted. | ||
253 | -- If it contains a field called ANY, then its type will be | ||
254 | -- used to check any unknown fields. If a field is prefixed | ||
255 | -- with MUST_, it is mandatory; its absence from the table is | ||
256 | -- a type error. | ||
257 | -- Tables are type checked recursively. | ||
258 | -- @param version string: The version of tbl. | ||
259 | -- @param tbl table: The table to be type checked. | ||
260 | -- @param typetbl table: The type-checking table, containing | ||
261 | -- values for recognized fields in the checked table. | ||
262 | -- @param context string: A string indicating the "context" where the | ||
263 | -- error occurred (such as the name of the table the item is a part of), | ||
264 | -- to be used by error messages. | ||
265 | -- @return boolean or (nil, string): true if type checking | ||
266 | -- succeeded, or nil and an error message if it failed. | ||
267 | type_check_table = function(version, tbl, typetbl, context) | ||
268 | assert(type(version) == "string") | ||
269 | assert(type(tbl) == "table") | ||
270 | assert(type(typetbl) == "table") | ||
271 | |||
272 | local ok, err = check_version(version, typetbl, context) | ||
273 | if not ok then | ||
274 | return nil, err | ||
275 | end | ||
276 | |||
277 | for k, v in pairs(tbl) do | ||
278 | local t = typetbl[k] or typetbl._any | ||
279 | if t then | ||
280 | local ok, err = type_check_item(version, v, t, mkfield(context, k)) | ||
281 | if not ok then return nil, err end | ||
282 | elseif typetbl._more then | ||
283 | -- Accept unknown field | ||
284 | else | ||
285 | if not cfg.accept_unknown_fields then | ||
286 | return nil, "Unknown field "..k | ||
287 | end | ||
288 | end | ||
289 | end | ||
290 | for k, v in pairs(typetbl) do | ||
291 | if k:sub(1,1) ~= "_" and v._mandatory then | ||
292 | if not tbl[k] then | ||
293 | return nil, "Mandatory field "..mkfield(context, k).." is missing." | ||
294 | end | ||
295 | end | ||
296 | end | ||
297 | return true | ||
298 | end | ||
299 | |||
300 | local function check_undeclared_globals(globals, typetbl) | ||
301 | local undeclared = {} | ||
302 | for glob, _ in pairs(globals) do | ||
303 | if not (typetbl[glob] or typetbl["MUST_"..glob]) then | ||
304 | table.insert(undeclared, glob) | ||
305 | end | ||
306 | end | ||
307 | if #undeclared == 1 then | ||
308 | return nil, "Unknown variable: "..undeclared[1] | ||
309 | elseif #undeclared > 1 then | ||
310 | return nil, "Unknown variables: "..table.concat(undeclared, ", ") | ||
311 | end | ||
312 | return true | ||
313 | end | ||
314 | |||
315 | --- Type check a rockspec table. | 116 | --- Type check a rockspec table. |
316 | -- Verify the correctness of elements from a | 117 | -- Verify the correctness of elements from a |
317 | -- rockspec table, reporting on unknown fields and type | 118 | -- rockspec table, reporting on unknown fields and type |
@@ -323,22 +124,9 @@ function type_check.type_check_rockspec(rockspec, globals) | |||
323 | if not rockspec.rockspec_format then | 124 | if not rockspec.rockspec_format then |
324 | rockspec.rockspec_format = "1.0" | 125 | rockspec.rockspec_format = "1.0" |
325 | end | 126 | end |
326 | local ok, err = check_undeclared_globals(globals, rockspec_types) | 127 | local ok, err = type_check.check_undeclared_globals(globals, rockspec_types) |
327 | if not ok then return nil, err end | ||
328 | return type_check_table(rockspec.rockspec_format, rockspec, rockspec_types, "") | ||
329 | end | ||
330 | |||
331 | --- Type check a manifest table. | ||
332 | -- Verify the correctness of elements from a | ||
333 | -- manifest table, reporting on unknown fields and type | ||
334 | -- mismatches. | ||
335 | -- @return boolean or (nil, string): true if type checking | ||
336 | -- succeeded, or nil and an error message if it failed. | ||
337 | function type_check.type_check_manifest(manifest, globals) | ||
338 | assert(type(manifest) == "table") | ||
339 | local ok, err = check_undeclared_globals(globals, manifest_types) | ||
340 | if not ok then return nil, err end | 128 | if not ok then return nil, err end |
341 | return type_check_table("1.0", manifest, manifest_types, "") | 129 | return type_check.type_check_table(rockspec.rockspec_format, rockspec, rockspec_types, "") |
342 | end | 130 | end |
343 | 131 | ||
344 | return type_check | 132 | return type_check |
diff --git a/src/luarocks/upload/api.lua b/src/luarocks/upload/api.lua index 2f0fa815..99162e75 100644 --- a/src/luarocks/upload/api.lua +++ b/src/luarocks/upload/api.lua | |||
@@ -1,7 +1,7 @@ | |||
1 | 1 | ||
2 | local api = {} | 2 | local api = {} |
3 | 3 | ||
4 | local cfg = require("luarocks.cfg") | 4 | local cfg = require("luarocks.core.cfg") |
5 | local fs = require("luarocks.fs") | 5 | local fs = require("luarocks.fs") |
6 | local dir = require("luarocks.dir") | 6 | local dir = require("luarocks.dir") |
7 | local util = require("luarocks.util") | 7 | local util = require("luarocks.util") |
diff --git a/src/luarocks/util.lua b/src/luarocks/util.lua index c9fb7d63..2c4724f4 100644 --- a/src/luarocks/util.lua +++ b/src/luarocks/util.lua | |||
@@ -2,9 +2,10 @@ | |||
2 | --- Assorted utilities for managing tables, plus a scheduler for rollback functions. | 2 | --- Assorted utilities for managing tables, plus a scheduler for rollback functions. |
3 | -- Does not requires modules directly (only as locals | 3 | -- Does not requires modules directly (only as locals |
4 | -- inside specific functions) to avoid interdependencies, | 4 | -- inside specific functions) to avoid interdependencies, |
5 | -- as this is used in the bootstrapping stage of luarocks.cfg. | 5 | -- as this is used in the bootstrapping stage of luarocks.core.cfg. |
6 | 6 | ||
7 | local util = {} | 7 | local util = {} |
8 | setmetatable(util, { __index = require("luarocks.core.util") }) | ||
8 | 9 | ||
9 | local unpack = unpack or table.unpack | 10 | local unpack = unpack or table.unpack |
10 | 11 | ||
@@ -86,7 +87,9 @@ local supported_flags = { | |||
86 | ["help"] = true, | 87 | ["help"] = true, |
87 | ["home"] = true, | 88 | ["home"] = true, |
88 | ["homepage"] = "\"<url>\"", | 89 | ["homepage"] = "\"<url>\"", |
90 | ["issues"] = true, | ||
89 | ["keep"] = true, | 91 | ["keep"] = true, |
92 | ["labels"] = true, | ||
90 | ["lib"] = "<library>", | 93 | ["lib"] = "<library>", |
91 | ["license"] = "\"<text>\"", | 94 | ["license"] = "\"<text>\"", |
92 | ["list"] = true, | 95 | ["list"] = true, |
@@ -196,34 +199,6 @@ function util.parse_flags(...) | |||
196 | return flags, unpack(out) | 199 | return flags, unpack(out) |
197 | end | 200 | end |
198 | 201 | ||
199 | -- Adds legacy 'run' function to a command module. | ||
200 | -- @param command table: command module with 'command' function, | ||
201 | -- the added 'run' function calls it after parseing command-line arguments. | ||
202 | function util.add_run_function(command) | ||
203 | command.run = function(...) return command.command(util.parse_flags(...)) end | ||
204 | end | ||
205 | |||
206 | --- Merges contents of src on top of dst's contents. | ||
207 | -- @param dst Destination table, which will receive src's contents. | ||
208 | -- @param src Table which provides new contents to dst. | ||
209 | -- @see platform_overrides | ||
210 | function util.deep_merge(dst, src) | ||
211 | for k, v in pairs(src) do | ||
212 | if type(v) == "table" then | ||
213 | if not dst[k] then | ||
214 | dst[k] = {} | ||
215 | end | ||
216 | if type(dst[k]) == "table" then | ||
217 | util.deep_merge(dst[k], v) | ||
218 | else | ||
219 | dst[k] = v | ||
220 | end | ||
221 | else | ||
222 | dst[k] = v | ||
223 | end | ||
224 | end | ||
225 | end | ||
226 | |||
227 | --- Perform platform-specific overrides on a table. | 202 | --- Perform platform-specific overrides on a table. |
228 | -- Overrides values of table with the contents of the appropriate | 203 | -- Overrides values of table with the contents of the appropriate |
229 | -- subset of its "platforms" field. The "platforms" field should | 204 | -- subset of its "platforms" field. The "platforms" field should |
@@ -240,7 +215,7 @@ end | |||
240 | function util.platform_overrides(tbl) | 215 | function util.platform_overrides(tbl) |
241 | assert(type(tbl) == "table" or not tbl) | 216 | assert(type(tbl) == "table" or not tbl) |
242 | 217 | ||
243 | local cfg = require("luarocks.cfg") | 218 | local cfg = require("luarocks.core.cfg") |
244 | 219 | ||
245 | if not tbl then return end | 220 | if not tbl then return end |
246 | 221 | ||
@@ -257,19 +232,6 @@ end | |||
257 | 232 | ||
258 | local var_format_pattern = "%$%((%a[%a%d_]+)%)" | 233 | local var_format_pattern = "%$%((%a[%a%d_]+)%)" |
259 | 234 | ||
260 | --- Create a new shallow copy of a table: a new table with | ||
261 | -- the same keys and values. Keys point to the same objects as | ||
262 | -- the original table (ie, does not copy recursively). | ||
263 | -- @param tbl table: the input table | ||
264 | -- @return table: a new table with the same contents. | ||
265 | function util.make_shallow_copy(tbl) | ||
266 | local copy = {} | ||
267 | for k,v in pairs(tbl) do | ||
268 | copy[k] = v | ||
269 | end | ||
270 | return copy | ||
271 | end | ||
272 | |||
273 | -- Check if a set of needed variables are referenced | 235 | -- Check if a set of needed variables are referenced |
274 | -- somewhere in a list of definitions, warning the user | 236 | -- somewhere in a list of definitions, warning the user |
275 | -- about any unused ones. Each key in needed_set should | 237 | -- about any unused ones. Each key in needed_set should |
@@ -332,86 +294,6 @@ function util.variable_substitutions(tbl, vars) | |||
332 | end | 294 | end |
333 | end | 295 | end |
334 | 296 | ||
335 | --- Return an array of keys of a table. | ||
336 | -- @param tbl table: The input table. | ||
337 | -- @return table: The array of keys. | ||
338 | function util.keys(tbl) | ||
339 | local ks = {} | ||
340 | for k,_ in pairs(tbl) do | ||
341 | table.insert(ks, k) | ||
342 | end | ||
343 | return ks | ||
344 | end | ||
345 | |||
346 | local function default_sort(a, b) | ||
347 | local ta = type(a) | ||
348 | local tb = type(b) | ||
349 | if ta == "number" and tb == "number" then | ||
350 | return a < b | ||
351 | elseif ta == "number" then | ||
352 | return true | ||
353 | elseif tb == "number" then | ||
354 | return false | ||
355 | else | ||
356 | return tostring(a) < tostring(b) | ||
357 | end | ||
358 | end | ||
359 | |||
360 | --- A table iterator generator that returns elements sorted by key, | ||
361 | -- to be used in "for" loops. | ||
362 | -- @param tbl table: The table to be iterated. | ||
363 | -- @param sort_function function or table or nil: An optional comparison function | ||
364 | -- to be used by table.sort when sorting keys, or an array listing an explicit order | ||
365 | -- for keys. If a value itself is an array, it is taken so that the first element | ||
366 | -- is a string representing the field name, and the second element is a priority table | ||
367 | -- for that key, which is returned by the iterator as the third value after the key | ||
368 | -- and the value. | ||
369 | -- @return function: the iterator function. | ||
370 | function util.sortedpairs(tbl, sort_function) | ||
371 | sort_function = sort_function or default_sort | ||
372 | local keys = util.keys(tbl) | ||
373 | local sub_orders = {} | ||
374 | |||
375 | if type(sort_function) == "function" then | ||
376 | table.sort(keys, sort_function) | ||
377 | else | ||
378 | local order = sort_function | ||
379 | local ordered_keys = {} | ||
380 | local all_keys = keys | ||
381 | keys = {} | ||
382 | |||
383 | for _, order_entry in ipairs(order) do | ||
384 | local key, sub_order | ||
385 | if type(order_entry) == "table" then | ||
386 | key = order_entry[1] | ||
387 | sub_order = order_entry[2] | ||
388 | else | ||
389 | key = order_entry | ||
390 | end | ||
391 | |||
392 | if tbl[key] then | ||
393 | ordered_keys[key] = true | ||
394 | sub_orders[key] = sub_order | ||
395 | table.insert(keys, key) | ||
396 | end | ||
397 | end | ||
398 | |||
399 | table.sort(all_keys, default_sort) | ||
400 | for _, key in ipairs(all_keys) do | ||
401 | if not ordered_keys[key] then | ||
402 | table.insert(keys, key) | ||
403 | end | ||
404 | end | ||
405 | end | ||
406 | |||
407 | local i = 1 | ||
408 | return function() | ||
409 | local key = keys[i] | ||
410 | i = i + 1 | ||
411 | return key, tbl[key], sub_orders[key] | ||
412 | end | ||
413 | end | ||
414 | |||
415 | function util.lua_versions() | 297 | function util.lua_versions() |
416 | local versions = { "5.1", "5.2", "5.3" } | 298 | local versions = { "5.1", "5.2", "5.3" } |
417 | local i = 0 | 299 | local i = 0 |
@@ -431,12 +313,6 @@ function util.printout(...) | |||
431 | io.stdout:write("\n") | 313 | io.stdout:write("\n") |
432 | end | 314 | end |
433 | 315 | ||
434 | --- Print a line to standard error | ||
435 | function util.printerr(...) | ||
436 | io.stderr:write(table.concat({...},"\t")) | ||
437 | io.stderr:write("\n") | ||
438 | end | ||
439 | |||
440 | --- Display a warning message. | 316 | --- Display a warning message. |
441 | -- @param msg string: the warning message | 317 | -- @param msg string: the warning message |
442 | function util.warning(msg) | 318 | function util.warning(msg) |
@@ -465,7 +341,7 @@ function util.this_program(default) | |||
465 | end | 341 | end |
466 | 342 | ||
467 | function util.deps_mode_help(program) | 343 | function util.deps_mode_help(program) |
468 | local cfg = require("luarocks.cfg") | 344 | local cfg = require("luarocks.core.cfg") |
469 | return [[ | 345 | return [[ |
470 | --deps-mode=<mode> How to handle dependencies. Four modes are supported: | 346 | --deps-mode=<mode> How to handle dependencies. Four modes are supported: |
471 | * all - use all trees from the rocks_trees list | 347 | * all - use all trees from the rocks_trees list |
@@ -488,7 +364,7 @@ function util.see_help(command, program) | |||
488 | end | 364 | end |
489 | 365 | ||
490 | function util.announce_install(rockspec) | 366 | function util.announce_install(rockspec) |
491 | local cfg = require("luarocks.cfg") | 367 | local cfg = require("luarocks.core.cfg") |
492 | local path = require("luarocks.path") | 368 | local path = require("luarocks.path") |
493 | 369 | ||
494 | local suffix = "" | 370 | local suffix = "" |
@@ -511,7 +387,7 @@ local function collect_rockspecs(versions, paths, unnamed_paths, subdir) | |||
511 | local fs = require("luarocks.fs") | 387 | local fs = require("luarocks.fs") |
512 | local dir = require("luarocks.dir") | 388 | local dir = require("luarocks.dir") |
513 | local path = require("luarocks.path") | 389 | local path = require("luarocks.path") |
514 | local deps = require("luarocks.deps") | 390 | local vers = require("luarocks.vers") |
515 | 391 | ||
516 | if fs.is_dir(subdir) then | 392 | if fs.is_dir(subdir) then |
517 | for file in fs.dir(subdir) do | 393 | for file in fs.dir(subdir) do |
@@ -521,7 +397,7 @@ local function collect_rockspecs(versions, paths, unnamed_paths, subdir) | |||
521 | local rock, version = path.parse_name(file) | 397 | local rock, version = path.parse_name(file) |
522 | 398 | ||
523 | if rock then | 399 | if rock then |
524 | if not versions[rock] or deps.compare_versions(version, versions[rock]) then | 400 | if not versions[rock] or vers.compare_versions(version, versions[rock]) then |
525 | versions[rock] = version | 401 | versions[rock] = version |
526 | paths[rock] = file | 402 | paths[rock] = file |
527 | end | 403 | end |
@@ -566,135 +442,6 @@ function util.get_default_rockspec() | |||
566 | end | 442 | end |
567 | end | 443 | end |
568 | 444 | ||
569 | -- from http://lua-users.org/wiki/SplitJoin | ||
570 | -- by PhilippeLhoste | ||
571 | function util.split_string(str, delim, maxNb) | ||
572 | -- Eliminate bad cases... | ||
573 | if string.find(str, delim) == nil then | ||
574 | return { str } | ||
575 | end | ||
576 | if maxNb == nil or maxNb < 1 then | ||
577 | maxNb = 0 -- No limit | ||
578 | end | ||
579 | local result = {} | ||
580 | local pat = "(.-)" .. delim .. "()" | ||
581 | local nb = 0 | ||
582 | local lastPos | ||
583 | for part, pos in string.gmatch(str, pat) do | ||
584 | nb = nb + 1 | ||
585 | result[nb] = part | ||
586 | lastPos = pos | ||
587 | if nb == maxNb then break end | ||
588 | end | ||
589 | -- Handle the last field | ||
590 | if nb ~= maxNb then | ||
591 | result[nb + 1] = string.sub(str, lastPos) | ||
592 | end | ||
593 | return result | ||
594 | end | ||
595 | |||
596 | --- Remove repeated entries from a path-style string. | ||
597 | -- Example: given ("a;b;c;a;b;d", ";"), returns "a;b;c;d". | ||
598 | -- @param list string: A path string (from $PATH or package.path) | ||
599 | -- @param sep string: The separator | ||
600 | function util.remove_path_dupes(list, sep) | ||
601 | assert(type(list) == "string") | ||
602 | assert(type(sep) == "string") | ||
603 | local parts = util.split_string(list, sep) | ||
604 | local final, entries = {}, {} | ||
605 | for _, part in ipairs(parts) do | ||
606 | part = part:gsub("//", "/") | ||
607 | if not entries[part] then | ||
608 | table.insert(final, part) | ||
609 | entries[part] = true | ||
610 | end | ||
611 | end | ||
612 | return table.concat(final, sep) | ||
613 | end | ||
614 | |||
615 | --- | ||
616 | -- Formats tables with cycles recursively to any depth. | ||
617 | -- References to other tables are shown as values. | ||
618 | -- Self references are indicated. | ||
619 | -- The string returned is "Lua code", which can be procesed | ||
620 | -- (in the case in which indent is composed by spaces or "--"). | ||
621 | -- Userdata and function keys and values are shown as strings, | ||
622 | -- which logically are exactly not equivalent to the original code. | ||
623 | -- This routine can serve for pretty formating tables with | ||
624 | -- proper indentations, apart from printing them: | ||
625 | -- io.write(table.show(t, "t")) -- a typical use | ||
626 | -- Written by Julio Manuel Fernandez-Diaz, | ||
627 | -- Heavily based on "Saving tables with cycles", PIL2, p. 113. | ||
628 | -- @param t table: is the table. | ||
629 | -- @param name string: is the name of the table (optional) | ||
630 | -- @param indent string: is a first indentation (optional). | ||
631 | -- @return string: the pretty-printed table | ||
632 | function util.show_table(t, name, indent) | ||
633 | local cart -- a container | ||
634 | local autoref -- for self references | ||
635 | |||
636 | local function isemptytable(t) return next(t) == nil end | ||
637 | |||
638 | local function basicSerialize (o) | ||
639 | local so = tostring(o) | ||
640 | if type(o) == "function" then | ||
641 | local info = debug.getinfo(o, "S") | ||
642 | -- info.name is nil because o is not a calling level | ||
643 | if info.what == "C" then | ||
644 | return ("%q"):format(so .. ", C function") | ||
645 | else | ||
646 | -- the information is defined through lines | ||
647 | return ("%q"):format(so .. ", defined in (" .. info.linedefined .. "-" .. info.lastlinedefined .. ")" .. info.source) | ||
648 | end | ||
649 | elseif type(o) == "number" then | ||
650 | return so | ||
651 | else | ||
652 | return ("%q"):format(so) | ||
653 | end | ||
654 | end | ||
655 | |||
656 | local function addtocart (value, name, indent, saved, field) | ||
657 | indent = indent or "" | ||
658 | saved = saved or {} | ||
659 | field = field or name | ||
660 | |||
661 | cart = cart .. indent .. field | ||
662 | |||
663 | if type(value) ~= "table" then | ||
664 | cart = cart .. " = " .. basicSerialize(value) .. ";\n" | ||
665 | else | ||
666 | if saved[value] then | ||
667 | cart = cart .. " = {}; -- " .. saved[value] .. " (self reference)\n" | ||
668 | autoref = autoref .. name .. " = " .. saved[value] .. ";\n" | ||
669 | else | ||
670 | saved[value] = name | ||
671 | --if tablecount(value) == 0 then | ||
672 | if isemptytable(value) then | ||
673 | cart = cart .. " = {};\n" | ||
674 | else | ||
675 | cart = cart .. " = {\n" | ||
676 | for k, v in pairs(value) do | ||
677 | k = basicSerialize(k) | ||
678 | local fname = ("%s[%s]"):format(name, k) | ||
679 | field = ("[%s]"):format(k) | ||
680 | -- three spaces between levels | ||
681 | addtocart(v, fname, indent .. " ", saved, field) | ||
682 | end | ||
683 | cart = cart .. indent .. "};\n" | ||
684 | end | ||
685 | end | ||
686 | end | ||
687 | end | ||
688 | |||
689 | name = name or "__unnamed__" | ||
690 | if type(t) ~= "table" then | ||
691 | return name .. " = " .. basicSerialize(t) | ||
692 | end | ||
693 | cart, autoref = "", "" | ||
694 | addtocart(t, name, indent) | ||
695 | return cart .. autoref | ||
696 | end | ||
697 | |||
698 | function util.array_contains(tbl, value) | 445 | function util.array_contains(tbl, value) |
699 | for _, v in ipairs(tbl) do | 446 | for _, v in ipairs(tbl) do |
700 | if v == value then | 447 | if v == value then |
diff --git a/src/luarocks/validate.lua b/src/luarocks/validate.lua deleted file mode 100644 index c4570aa4..00000000 --- a/src/luarocks/validate.lua +++ /dev/null | |||
@@ -1,159 +0,0 @@ | |||
1 | |||
2 | --- Sandboxed test of build/install of all packages in a repository (unfinished and disabled). | ||
3 | local validate = {} | ||
4 | package.loaded["luarocks.validate"] = validate | ||
5 | |||
6 | local fs = require("luarocks.fs") | ||
7 | local dir = require("luarocks.dir") | ||
8 | local path = require("luarocks.path") | ||
9 | local cfg = require("luarocks.cfg") | ||
10 | local build = require("luarocks.build") | ||
11 | local install = require("luarocks.install") | ||
12 | local util = require("luarocks.util") | ||
13 | |||
14 | util.add_run_function(validate) | ||
15 | validate.help_summary = "Sandboxed test of build/install of all packages in a repository." | ||
16 | |||
17 | validate.help = [[ | ||
18 | <argument>, if given, is a local repository pathname. | ||
19 | ]] | ||
20 | |||
21 | local function save_settings(repo) | ||
22 | local protocol, path = dir.split_url(repo) | ||
23 | table.insert(cfg.rocks_servers, 1, protocol.."://"..path) | ||
24 | return { | ||
25 | root_dir = cfg.root_dir, | ||
26 | rocks_dir = cfg.rocks_dir, | ||
27 | deploy_bin_dir = cfg.deploy_bin_dir, | ||
28 | deploy_lua_dir = cfg.deploy_lua_dir, | ||
29 | deploy_lib_dir = cfg.deploy_lib_dir, | ||
30 | } | ||
31 | end | ||
32 | |||
33 | local function restore_settings(settings) | ||
34 | cfg.root_dir = settings.root_dir | ||
35 | cfg.rocks_dir = settings.rocks_dir | ||
36 | cfg.deploy_bin_dir = settings.deploy_bin_dir | ||
37 | cfg.deploy_lua_dir = settings.deploy_lua_dir | ||
38 | cfg.deploy_lib_dir = settings.deploy_lib_dir | ||
39 | cfg.variables.ROCKS_TREE = settings.rocks_dir | ||
40 | cfg.variables.SCRIPTS_DIR = settings.deploy_bin_dir | ||
41 | table.remove(cfg.rocks_servers, 1) | ||
42 | end | ||
43 | |||
44 | local function prepare_sandbox(file) | ||
45 | local root_dir = fs.make_temp_dir(file):gsub("/+$", "") | ||
46 | cfg.root_dir = root_dir | ||
47 | cfg.rocks_dir = path.rocks_dir(root_dir) | ||
48 | cfg.deploy_bin_dir = path.deploy_bin_dir(root_dir) | ||
49 | cfg.variables.ROCKS_TREE = cfg.rocks_dir | ||
50 | cfg.variables.SCRIPTS_DIR = cfg.deploy_bin_dir | ||
51 | return root_dir | ||
52 | end | ||
53 | |||
54 | local function validate_rockspec(file) | ||
55 | local ok, err, errcode = build.build_rockspec(file, true, "one") | ||
56 | if not ok then | ||
57 | util.printerr(err) | ||
58 | end | ||
59 | return ok, err, errcode | ||
60 | end | ||
61 | |||
62 | local function validate_src_rock(file) | ||
63 | local ok, err, errcode = build.build_rock(file, false, "one") | ||
64 | if not ok then | ||
65 | util.printerr(err) | ||
66 | end | ||
67 | return ok, err, errcode | ||
68 | end | ||
69 | |||
70 | local function validate_rock(file) | ||
71 | local ok, err, errcode = install.install_binary_rock(file, "one") | ||
72 | if not ok then | ||
73 | util.printerr(err) | ||
74 | end | ||
75 | return ok, err, errcode | ||
76 | end | ||
77 | |||
78 | function validate.command(flags, repo) | ||
79 | repo = repo or cfg.rocks_dir | ||
80 | |||
81 | util.printout("Verifying contents of "..repo) | ||
82 | |||
83 | local results = { | ||
84 | ok = {} | ||
85 | } | ||
86 | local settings = save_settings(repo) | ||
87 | local sandbox | ||
88 | if flags["quick"] then | ||
89 | sandbox = prepare_sandbox("luarocks_validate") | ||
90 | end | ||
91 | if not fs.exists(repo) then | ||
92 | return nil, repo.." is not a local repository." | ||
93 | end | ||
94 | for file in fs.dir(repo) do for _=1,1 do | ||
95 | if file == "manifest" or file == "index.html" then | ||
96 | break -- continue for | ||
97 | end | ||
98 | local pathname = fs.absolute_name(dir.path(repo, file)) | ||
99 | if not flags["quick"] then | ||
100 | sandbox = prepare_sandbox(file) | ||
101 | end | ||
102 | local ok, err, errcode | ||
103 | util.printout() | ||
104 | util.printout("Verifying "..pathname) | ||
105 | if file:match("%.rockspec$") then | ||
106 | ok, err, errcode = validate_rockspec(pathname, "one") | ||
107 | elseif file:match("%.src%.rock$") then | ||
108 | ok, err, errcode = validate_src_rock(pathname) | ||
109 | elseif file:match("%.rock$") then | ||
110 | ok, err, errcode = validate_rock(pathname) | ||
111 | end | ||
112 | if ok then | ||
113 | table.insert(results.ok, {file=file} ) | ||
114 | else | ||
115 | if not errcode then | ||
116 | errcode = "misc" | ||
117 | end | ||
118 | if not results[errcode] then | ||
119 | results[errcode] = {} | ||
120 | end | ||
121 | table.insert(results[errcode], {file=file, err=err} ) | ||
122 | end | ||
123 | util.run_scheduled_functions() | ||
124 | if not flags["quick"] then | ||
125 | fs.delete(sandbox) | ||
126 | end | ||
127 | repeat until not fs.pop_dir() | ||
128 | end end | ||
129 | if flags["quick"] then | ||
130 | fs.delete(sandbox) | ||
131 | end | ||
132 | restore_settings(settings) | ||
133 | util.title("Results:") | ||
134 | util.printout("OK: "..tostring(#results.ok)) | ||
135 | for _, entry in ipairs(results.ok) do | ||
136 | util.printout(entry.file) | ||
137 | end | ||
138 | for errcode, errors in pairs(results) do | ||
139 | if errcode ~= "ok" then | ||
140 | util.printout() | ||
141 | util.printout(errcode.." errors: "..tostring(#errors)) | ||
142 | for _, entry in ipairs(errors) do | ||
143 | util.printout(entry.file, entry.err) | ||
144 | end | ||
145 | end | ||
146 | end | ||
147 | |||
148 | util.title("Summary:") | ||
149 | local total = 0 | ||
150 | for errcode, errors in pairs(results) do | ||
151 | util.printout(errcode..": "..tostring(#errors)) | ||
152 | total = total + #errors | ||
153 | end | ||
154 | util.printout("Total: "..total) | ||
155 | return true | ||
156 | end | ||
157 | |||
158 | |||
159 | return validate | ||
diff --git a/src/luarocks/vers.lua b/src/luarocks/vers.lua new file mode 100644 index 00000000..6ce5d738 --- /dev/null +++ b/src/luarocks/vers.lua | |||
@@ -0,0 +1,138 @@ | |||
1 | |||
2 | --- Dependency format handling functions. | ||
3 | -- Dependencies are represented in LuaRocks through strings with | ||
4 | -- a package name followed by a comma-separated list of constraints. | ||
5 | -- Each constraint consists of an operator and a version number. | ||
6 | -- In this string format, version numbers are represented as | ||
7 | -- naturally as possible, like they are used by upstream projects | ||
8 | -- (e.g. "2.0beta3"). Internally, LuaRocks converts them to a purely | ||
9 | -- numeric representation, allowing comparison following some | ||
10 | -- "common sense" heuristics. The precise specification of the | ||
11 | -- comparison criteria is the source code of this module. | ||
12 | local vers = {} | ||
13 | setmetatable(vers, { __index = require("luarocks.core.vers") }) | ||
14 | |||
15 | --- Check if rockspec format version satisfies version requirement. | ||
16 | -- @param rockspec table: The rockspec table. | ||
17 | -- @param version string: required version. | ||
18 | -- @return boolean: true if rockspec format matches version or is newer, false otherwise. | ||
19 | function vers.format_is_at_least(rockspec, version) | ||
20 | local rockspec_format = rockspec.rockspec_format or "1.0" | ||
21 | return vers.parse_version(rockspec_format) >= vers.parse_version(version) | ||
22 | end | ||
23 | |||
24 | local operators = { | ||
25 | ["=="] = "==", | ||
26 | ["~="] = "~=", | ||
27 | [">"] = ">", | ||
28 | ["<"] = "<", | ||
29 | [">="] = ">=", | ||
30 | ["<="] = "<=", | ||
31 | ["~>"] = "~>", | ||
32 | -- plus some convenience translations | ||
33 | [""] = "==", | ||
34 | ["="] = "==", | ||
35 | ["!="] = "~=" | ||
36 | } | ||
37 | |||
38 | --- Consumes a constraint from a string, converting it to table format. | ||
39 | -- For example, a string ">= 1.0, > 2.0" is converted to a table in the | ||
40 | -- format {op = ">=", version={1,0}} and the rest, "> 2.0", is returned | ||
41 | -- back to the caller. | ||
42 | -- @param input string: A list of constraints in string format. | ||
43 | -- @return (table, string) or nil: A table representing the same | ||
44 | -- constraints and the string with the unused input, or nil if the | ||
45 | -- input string is invalid. | ||
46 | local function parse_constraint(input) | ||
47 | assert(type(input) == "string") | ||
48 | |||
49 | local no_upgrade, op, version, rest = input:match("^(@?)([<>=~!]*)%s*([%w%.%_%-]+)[%s,]*(.*)") | ||
50 | local _op = operators[op] | ||
51 | version = vers.parse_version(version) | ||
52 | if not _op then | ||
53 | return nil, "Encountered bad constraint operator: '"..tostring(op).."' in '"..input.."'" | ||
54 | end | ||
55 | if not version then | ||
56 | return nil, "Could not parse version from constraint: '"..input.."'" | ||
57 | end | ||
58 | return { op = _op, version = version, no_upgrade = no_upgrade=="@" and true or nil }, rest | ||
59 | end | ||
60 | |||
61 | --- Convert a list of constraints from string to table format. | ||
62 | -- For example, a string ">= 1.0, < 2.0" is converted to a table in the format | ||
63 | -- {{op = ">=", version={1,0}}, {op = "<", version={2,0}}}. | ||
64 | -- Version tables use a metatable allowing later comparison through | ||
65 | -- relational operators. | ||
66 | -- @param input string: A list of constraints in string format. | ||
67 | -- @return table or nil: A table representing the same constraints, | ||
68 | -- or nil if the input string is invalid. | ||
69 | function vers.parse_constraints(input) | ||
70 | assert(type(input) == "string") | ||
71 | |||
72 | local constraints, oinput, constraint = {}, input | ||
73 | while #input > 0 do | ||
74 | constraint, input = parse_constraint(input) | ||
75 | if constraint then | ||
76 | table.insert(constraints, constraint) | ||
77 | else | ||
78 | return nil, "Failed to parse constraint '"..tostring(oinput).."' with error: ".. input | ||
79 | end | ||
80 | end | ||
81 | return constraints | ||
82 | end | ||
83 | |||
84 | --- Convert a dependency from string to table format. | ||
85 | -- For example, a string "foo >= 1.0, < 2.0" | ||
86 | -- is converted to a table in the format | ||
87 | -- {name = "foo", constraints = {{op = ">=", version={1,0}}, | ||
88 | -- {op = "<", version={2,0}}}}. Version tables use a metatable | ||
89 | -- allowing later comparison through relational operators. | ||
90 | -- @param dep string: A dependency in string format | ||
91 | -- as entered in rockspec files. | ||
92 | -- @return table or nil: A table representing the same dependency relation, | ||
93 | -- or nil if the input string is invalid. | ||
94 | function vers.parse_dep(dep) | ||
95 | assert(type(dep) == "string") | ||
96 | |||
97 | local name, rest = dep:match("^%s*([a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*(.*)") | ||
98 | if not name then return nil, "failed to extract dependency name from '"..tostring(dep).."'" end | ||
99 | local constraints, err = vers.parse_constraints(rest) | ||
100 | if not constraints then return nil, err end | ||
101 | return { name = name, constraints = constraints } | ||
102 | end | ||
103 | |||
104 | --- Convert a version table to a string. | ||
105 | -- @param v table: The version table | ||
106 | -- @param internal boolean or nil: Whether to display versions in their | ||
107 | -- internal representation format or how they were specified. | ||
108 | -- @return string: The dependency information pretty-printed as a string. | ||
109 | function vers.show_version(v, internal) | ||
110 | assert(type(v) == "table") | ||
111 | assert(type(internal) == "boolean" or not internal) | ||
112 | |||
113 | return (internal | ||
114 | and table.concat(v, ":")..(v.revision and tostring(v.revision) or "") | ||
115 | or v.string) | ||
116 | end | ||
117 | |||
118 | --- Convert a dependency in table format to a string. | ||
119 | -- @param dep table: The dependency in table format | ||
120 | -- @param internal boolean or nil: Whether to display versions in their | ||
121 | -- internal representation format or how they were specified. | ||
122 | -- @return string: The dependency information pretty-printed as a string. | ||
123 | function vers.show_dep(dep, internal) | ||
124 | assert(type(dep) == "table") | ||
125 | assert(type(internal) == "boolean" or not internal) | ||
126 | |||
127 | if #dep.constraints > 0 then | ||
128 | local pretty = {} | ||
129 | for _, c in ipairs(dep.constraints) do | ||
130 | table.insert(pretty, c.op .. " " .. vers.show_version(c.version, internal)) | ||
131 | end | ||
132 | return dep.name.." "..table.concat(pretty, ", ") | ||
133 | else | ||
134 | return dep.name | ||
135 | end | ||
136 | end | ||
137 | |||
138 | return vers | ||