aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.setup.inc4
-rw-r--r--spec/build_spec.lua35
-rw-r--r--spec/doc_spec.lua8
-rw-r--r--spec/download_spec.lua21
-rw-r--r--spec/fetch_spec.lua7
-rw-r--r--spec/fixtures/a_repo/manifest20
-rw-r--r--spec/fixtures/a_repo/manifest-5.120
-rw-r--r--spec/fixtures/a_repo/manifest-5.220
-rw-r--r--spec/fixtures/a_repo/manifest-5.320
-rw-r--r--spec/install_spec.lua31
-rw-r--r--spec/list_spec.lua4
-rw-r--r--spec/pack_spec.lua76
-rw-r--r--spec/show_spec.lua2
-rw-r--r--spec/util/mock-server.lua3
-rw-r--r--spec/util/test_env.lua2
-rw-r--r--spec/write_rockspec_spec.lua10
-rw-r--r--src/luarocks/admin/index.lua2
-rw-r--r--src/luarocks/build.lua7
-rw-r--r--src/luarocks/cmd/build.lua50
-rw-r--r--src/luarocks/cmd/doc.lua9
-rw-r--r--src/luarocks/cmd/download.lua3
-rw-r--r--src/luarocks/cmd/install.lua56
-rw-r--r--src/luarocks/cmd/list.lua10
-rw-r--r--src/luarocks/cmd/make.lua2
-rw-r--r--src/luarocks/cmd/pack.lua3
-rw-r--r--src/luarocks/cmd/purge.lua4
-rw-r--r--src/luarocks/cmd/remove.lua4
-rw-r--r--src/luarocks/cmd/search.lua21
-rw-r--r--src/luarocks/cmd/show.lua20
-rw-r--r--src/luarocks/cmd/unpack.lua8
-rw-r--r--src/luarocks/cmd/write_rockspec.lua11
-rw-r--r--src/luarocks/core/util.lua6
-rw-r--r--src/luarocks/deps.lua16
-rw-r--r--src/luarocks/fetch.lua22
-rw-r--r--src/luarocks/fetch/git.lua4
-rw-r--r--src/luarocks/manif.lua21
-rw-r--r--src/luarocks/manif/writer.lua29
-rw-r--r--src/luarocks/pack.lua8
-rw-r--r--src/luarocks/path.lua13
-rw-r--r--src/luarocks/queries.lua174
-rw-r--r--src/luarocks/remove.lua4
-rw-r--r--src/luarocks/repos.lua2
-rw-r--r--src/luarocks/results.lua62
-rw-r--r--src/luarocks/search.lua230
-rw-r--r--src/luarocks/type/rockspec.lua18
-rw-r--r--src/luarocks/type_check.lua8
-rw-r--r--src/luarocks/util.lua46
-rw-r--r--src/luarocks/vers.lua126
48 files changed, 856 insertions, 426 deletions
diff --git a/Makefile.setup.inc b/Makefile.setup.inc
index d762f6f7..ed3face4 100644
--- a/Makefile.setup.inc
+++ b/Makefile.setup.inc
@@ -21,5 +21,5 @@ admin/cmd/make_manifest.lua admin/cmd/add.lua admin/cmd/remove.lua \
21admin/cmd/refresh_cache.lua remove.lua fetch/git_file.lua fetch/sscm.lua \ 21admin/cmd/refresh_cache.lua remove.lua fetch/git_file.lua fetch/sscm.lua \
22fetch/cvs.lua fetch/git_https.lua fetch/git_ssh.lua fetch/hg_http.lua \ 22fetch/cvs.lua fetch/git_https.lua fetch/git_ssh.lua fetch/hg_http.lua \
23fetch/git_http.lua fetch/svn.lua fetch/git.lua fetch/hg_ssh.lua \ 23fetch/git_http.lua fetch/svn.lua fetch/git.lua fetch/hg_ssh.lua \
24fetch/hg_https.lua fetch/hg.lua vers.lua core/vers.lua cmd/which.lua \ 24fetch/hg_https.lua fetch/hg.lua core/vers.lua cmd/which.lua \
25fun.lua type/manifest.lua type/rockspec.lua 25fun.lua type/manifest.lua type/rockspec.lua queries.lua results.lua
diff --git a/spec/build_spec.lua b/spec/build_spec.lua
index 2de05879..ed36dbd2 100644
--- a/spec/build_spec.lua
+++ b/spec/build_spec.lua
@@ -62,6 +62,7 @@ describe("LuaRocks build tests #blackbox #b_build", function()
62 end) 62 end)
63 63
64 it("LuaRocks build lpeg branch=master", function() 64 it("LuaRocks build lpeg branch=master", function()
65 -- FIXME should use dev package
65 assert.is_true(run.luarocks_bool("build --branch=master lpeg")) 66 assert.is_true(run.luarocks_bool("build --branch=master lpeg"))
66 assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lpeg/1.0.0-1/lpeg-1.0.0-1.rockspec")) 67 assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/lpeg/1.0.0-1/lpeg-1.0.0-1.rockspec"))
67 end) 68 end)
@@ -137,6 +138,40 @@ describe("LuaRocks build tests #blackbox #b_build", function()
137 end) 138 end)
138 end) 139 end)
139 140
141 describe("#namespaces", function()
142 it("builds a namespaced package from the command-line", function()
143 assert(run.luarocks_bool("build a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" ))
144 assert.is_false(run.luarocks_bool("show a_rock 1.0"))
145 assert(run.luarocks_bool("show a_rock 2.0"))
146 assert(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/2.0-1/rock_namespace"))
147 end)
148
149 it("builds a package with a namespaced dependency", function()
150 assert(run.luarocks_bool("build has_namespaced_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" ))
151 assert(run.luarocks_bool("show has_namespaced_dep"))
152 assert.is_false(run.luarocks_bool("show a_rock 1.0"))
153 assert(run.luarocks_bool("show a_rock 2.0"))
154 end)
155
156 it("builds a package reusing a namespaced dependency", function()
157 assert(run.luarocks_bool("build a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" ))
158 assert(run.luarocks_bool("show a_rock 2.0"))
159 assert(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/2.0-1/rock_namespace"))
160 local output = run.luarocks("build has_namespaced_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )
161 assert.has.no.match("Missing dependencies", output)
162 end)
163
164 it("builds a package considering namespace of locally installed package", function()
165 assert(run.luarocks_bool("build a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" ))
166 assert(run.luarocks_bool("show a_rock 2.0"))
167 assert(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/2.0-1/rock_namespace"))
168 local output = run.luarocks("build has_another_namespaced_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )
169 assert.has.match("Missing dependencies", output)
170 print(output)
171 assert(run.luarocks_bool("show a_rock 3.0"))
172 end)
173 end)
174
140 describe("LuaRocks build - more complex tests", function() 175 describe("LuaRocks build - more complex tests", function()
141 if test_env.TYPE_TEST_ENV == "full" then 176 if test_env.TYPE_TEST_ENV == "full" then
142 it("LuaRocks build luacheck show downloads test_config", function() 177 it("LuaRocks build luacheck show downloads test_config", function()
diff --git a/spec/doc_spec.lua b/spec/doc_spec.lua
index 5f503af2..6d91fc00 100644
--- a/spec/doc_spec.lua
+++ b/spec/doc_spec.lua
@@ -38,6 +38,14 @@ describe("LuaRocks doc tests #blackbox #b_doc", function()
38 assert.is.truthy(output:find("Local documentation directory not found")) 38 assert.is.truthy(output:find("Local documentation directory not found"))
39 end) 39 end)
40 end) 40 end)
41
42 describe("#namespaces", function()
43 it("retrieves docs for a namespaced package from the command-line", function()
44 assert(run.luarocks_bool("build a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" ))
45 assert(run.luarocks_bool("build a_rock --keep --server=" .. testing_paths.fixtures_dir .. "/a_repo" ))
46 assert.match("a_rock 2.0", run.luarocks("doc a_user/a_rock"))
47 end)
48 end)
41 49
42 describe("LuaRocks doc tests with flags", function() 50 describe("LuaRocks doc tests with flags", function()
43 it("LuaRocks doc of installed luarepl", function() 51 it("LuaRocks doc of installed luarepl", function()
diff --git a/spec/download_spec.lua b/spec/download_spec.lua
index 64443922..152470a5 100644
--- a/spec/download_spec.lua
+++ b/spec/download_spec.lua
@@ -1,6 +1,7 @@
1local test_env = require("spec.util.test_env") 1local test_env = require("spec.util.test_env")
2local lfs = require("lfs") 2local lfs = require("lfs")
3local run = test_env.run 3local run = test_env.run
4local testing_paths = test_env.testing_paths
4 5
5test_env.unload_luarocks() 6test_env.unload_luarocks()
6 7
@@ -33,4 +34,24 @@ describe("LuaRocks download tests #blackbox #b_download", function()
33 assert.is.truthy(lfs.attributes("validate-args-1.5.4-1.rockspec")) 34 assert.is.truthy(lfs.attributes("validate-args-1.5.4-1.rockspec"))
34 test_env.remove_files(lfs.currentdir(), "validate--args--") 35 test_env.remove_files(lfs.currentdir(), "validate--args--")
35 end) 36 end)
37
38 describe("#namespaces", function()
39 it("retrieves namespaced rockspec", function()
40 finally(function()
41 os.remove("a_rock-2.0-1.rockspec")
42 end)
43 assert(run.luarocks_bool("download a_user/a_rock --rockspec --server=" .. testing_paths.fixtures_dir .. "/a_repo" ))
44 assert(lfs.attributes("a_rock-2.0-1.rockspec"))
45 end)
46
47 it("retrieves namespaced rock", function()
48 finally(function()
49 os.remove("a_rock-2.0-1.src.rock")
50 end)
51 assert(run.luarocks_bool("download a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" ))
52 assert(lfs.attributes("a_rock-2.0-1.src.rock"))
53 end)
54 end)
55
56
36end) 57end)
diff --git a/spec/fetch_spec.lua b/spec/fetch_spec.lua
index 5f518e4d..79b160c1 100644
--- a/spec/fetch_spec.lua
+++ b/spec/fetch_spec.lua
@@ -3,7 +3,6 @@ local git_repo = require("spec.util.git_repo")
3 3
4test_env.unload_luarocks() 4test_env.unload_luarocks()
5local fetch = require("luarocks.fetch") 5local fetch = require("luarocks.fetch")
6local vers = require("luarocks.vers")
7 6
8describe("Luarocks fetch test #whitebox #w_fetch", function() 7describe("Luarocks fetch test #whitebox #w_fetch", function()
9 it("Fetch url to base dir", function() 8 it("Fetch url to base dir", function()
@@ -30,12 +29,14 @@ describe("Luarocks fetch test #whitebox #w_fetch", function()
30 29
31 it("from #git", function() 30 it("from #git", function()
32 local rockspec = { 31 local rockspec = {
33 format_is_at_least = vers.format_is_at_least, 32 format_is_at_least = function()
33 return true
34 end,
34 name = "testrock", 35 name = "testrock",
35 version = "dev-1", 36 version = "dev-1",
36 source = { 37 source = {
37 protocol = "git", 38 protocol = "git",
38 url = "git://localhost:20000/testrock", 39 url = "git://localhost/testrock",
39 }, 40 },
40 variables = { 41 variables = {
41 GIT = "git", 42 GIT = "git",
diff --git a/spec/fixtures/a_repo/manifest b/spec/fixtures/a_repo/manifest
index ea198207..141dafb5 100644
--- a/spec/fixtures/a_repo/manifest
+++ b/spec/fixtures/a_repo/manifest
@@ -10,5 +10,25 @@ repository = {
10 arch = "rockspec" 10 arch = "rockspec"
11 } 11 }
12 } 12 }
13 },
14 has_another_namespaced_dep = {
15 ["1.0-1"] = {
16 {
17 arch = "rockspec"
18 },
19 {
20 arch = "src"
21 }
22 }
23 },
24 has_namespaced_dep = {
25 ["1.0-1"] = {
26 {
27 arch = "rockspec"
28 },
29 {
30 arch = "src"
31 }
32 }
13 } 33 }
14} 34}
diff --git a/spec/fixtures/a_repo/manifest-5.1 b/spec/fixtures/a_repo/manifest-5.1
index ea198207..141dafb5 100644
--- a/spec/fixtures/a_repo/manifest-5.1
+++ b/spec/fixtures/a_repo/manifest-5.1
@@ -10,5 +10,25 @@ repository = {
10 arch = "rockspec" 10 arch = "rockspec"
11 } 11 }
12 } 12 }
13 },
14 has_another_namespaced_dep = {
15 ["1.0-1"] = {
16 {
17 arch = "rockspec"
18 },
19 {
20 arch = "src"
21 }
22 }
23 },
24 has_namespaced_dep = {
25 ["1.0-1"] = {
26 {
27 arch = "rockspec"
28 },
29 {
30 arch = "src"
31 }
32 }
13 } 33 }
14} 34}
diff --git a/spec/fixtures/a_repo/manifest-5.2 b/spec/fixtures/a_repo/manifest-5.2
index ea198207..141dafb5 100644
--- a/spec/fixtures/a_repo/manifest-5.2
+++ b/spec/fixtures/a_repo/manifest-5.2
@@ -10,5 +10,25 @@ repository = {
10 arch = "rockspec" 10 arch = "rockspec"
11 } 11 }
12 } 12 }
13 },
14 has_another_namespaced_dep = {
15 ["1.0-1"] = {
16 {
17 arch = "rockspec"
18 },
19 {
20 arch = "src"
21 }
22 }
23 },
24 has_namespaced_dep = {
25 ["1.0-1"] = {
26 {
27 arch = "rockspec"
28 },
29 {
30 arch = "src"
31 }
32 }
13 } 33 }
14} 34}
diff --git a/spec/fixtures/a_repo/manifest-5.3 b/spec/fixtures/a_repo/manifest-5.3
index ea198207..141dafb5 100644
--- a/spec/fixtures/a_repo/manifest-5.3
+++ b/spec/fixtures/a_repo/manifest-5.3
@@ -10,5 +10,25 @@ repository = {
10 arch = "rockspec" 10 arch = "rockspec"
11 } 11 }
12 } 12 }
13 },
14 has_another_namespaced_dep = {
15 ["1.0-1"] = {
16 {
17 arch = "rockspec"
18 },
19 {
20 arch = "src"
21 }
22 }
23 },
24 has_namespaced_dep = {
25 ["1.0-1"] = {
26 {
27 arch = "rockspec"
28 },
29 {
30 arch = "src"
31 }
32 }
13 } 33 }
14} 34}
diff --git a/spec/install_spec.lua b/spec/install_spec.lua
index 53c8f0d0..4043af35 100644
--- a/spec/install_spec.lua
+++ b/spec/install_spec.lua
@@ -77,11 +77,38 @@ describe("luarocks install #blackbox #b_install", function()
77 end) 77 end)
78 end) 78 end)
79 79
80 describe("#only namespaced packages", function() 80 describe("#namespaces", function()
81 it("installs a namespaced package from the command-line", function() 81 it("installs a namespaced package from the command-line", function()
82 assert(run.luarocks_bool("install a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) 82 assert(run.luarocks_bool("install a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" ))
83 assert.is_false(run.luarocks_bool("show a_rock 1.0")) 83 assert.is_false(run.luarocks_bool("show a_rock 1.0"))
84 assert(run.luarocks_bool("show a_rock 2.0")) 84 assert(run.luarocks_bool("show a_rock 2.0"))
85 assert(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/2.0-1/rock_namespace"))
86 end)
87
88 it("installs a package with a namespaced dependency", function()
89 assert(run.luarocks_bool("install has_namespaced_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" ))
90 assert(run.luarocks_bool("show has_namespaced_dep"))
91 assert.is_false(run.luarocks_bool("show a_rock 1.0"))
92 assert(run.luarocks_bool("show a_rock 2.0"))
93 assert(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/2.0-1/rock_namespace"))
94 end)
95
96 it("installs a package reusing a namespaced dependency", function()
97 assert(run.luarocks_bool("install a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" ))
98 assert(run.luarocks_bool("show a_rock 2.0"))
99 assert(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/2.0-1/rock_namespace"))
100 local output = run.luarocks("install has_namespaced_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )
101 assert.has.no.match("Missing dependencies", output)
102 end)
103
104 it("installs a package considering namespace of locally installed package", function()
105 assert(run.luarocks_bool("install a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" ))
106 assert(run.luarocks_bool("show a_rock 2.0"))
107 assert(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/2.0-1/rock_namespace"))
108 local output = run.luarocks("install has_another_namespaced_dep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )
109 assert.has.match("Missing dependencies", output)
110 print(output)
111 assert(run.luarocks_bool("show a_rock 3.0"))
85 end) 112 end)
86 end) 113 end)
87 114
@@ -155,7 +182,7 @@ describe("luarocks install #blackbox #b_install", function()
155 it("only-deps of luasocket packed rock", function() 182 it("only-deps of luasocket packed rock", function()
156 assert.is_true(run.luarocks_bool("build --pack-binary-rock luasocket 3.0rc1-2")) 183 assert.is_true(run.luarocks_bool("build --pack-binary-rock luasocket 3.0rc1-2"))
157 local output = run.luarocks("install --only-deps " .. "luasocket-3.0rc1-2." .. test_env.platform .. ".rock") 184 local output = run.luarocks("install --only-deps " .. "luasocket-3.0rc1-2." .. test_env.platform .. ".rock")
158 assert.are.same(output, "Successfully installed dependencies for luasocket 3.0rc1-2") 185 assert.are.same("Successfully installed dependencies for luasocket 3.0rc1-2", output:gsub("\n", ""))
159 assert.is_true(os.remove("luasocket-3.0rc1-2." .. test_env.platform .. ".rock")) 186 assert.is_true(os.remove("luasocket-3.0rc1-2." .. test_env.platform .. ".rock"))
160 end) 187 end)
161 188
diff --git a/spec/list_spec.lua b/spec/list_spec.lua
index 07d60bf0..d6aeef38 100644
--- a/spec/list_spec.lua
+++ b/spec/list_spec.lua
@@ -17,7 +17,7 @@ describe("LuaRocks list tests #blackbox #b_list", function()
17 17
18 it("LuaRocks list with no flags/arguments", function() 18 it("LuaRocks list with no flags/arguments", function()
19 local output = run.luarocks("list") 19 local output = run.luarocks("list")
20 assert.is.truthy(output:find("luacov")) 20 assert.match("luacov", output)
21 end) 21 end)
22 22
23 it("LuaRocks list porcelain", function() 23 it("LuaRocks list porcelain", function()
@@ -33,6 +33,6 @@ describe("LuaRocks list tests #blackbox #b_list", function()
33 33
34 it("LuaRocks list invalid tree", function() 34 it("LuaRocks list invalid tree", function()
35 local output = run.luarocks("--tree=/some/invalid/tree list") 35 local output = run.luarocks("--tree=/some/invalid/tree list")
36 assert(output:find("Installed rocks for Lua "..test_env.lua_version..":----------------", 1, true)) 36 assert(output:find("Installed rocks for Lua "..test_env.lua_version, 1, true))
37 end) 37 end)
38end) 38end)
diff --git a/spec/pack_spec.lua b/spec/pack_spec.lua
index 86b4e2b2..54d139e0 100644
--- a/spec/pack_spec.lua
+++ b/spec/pack_spec.lua
@@ -5,57 +5,89 @@ local testing_paths = test_env.testing_paths
5 5
6test_env.unload_luarocks() 6test_env.unload_luarocks()
7 7
8local extra_rocks = { 8local extra_rocks = test_env.mock_server_extra_rocks({
9 "/luasec-0.6-1.rockspec", 9 "/luasec-0.6-1.rockspec",
10 "/luassert-1.7.0-1.src.rock", 10 "/luassert-1.7.0-1.src.rock",
11 "/luasocket-3.0rc1-2.src.rock", 11 "/luasocket-3.0rc1-2.src.rock",
12 "/luasocket-3.0rc1-2.rockspec", 12 "/luasocket-3.0rc1-2.rockspec",
13 "/say-1.2-1.src.rock", 13 "/say-1.2-1.src.rock",
14 "/say-1.0-1.src.rock" 14 "/say-1.0-1.src.rock"
15} 15})
16 16
17describe("LuaRocks pack tests #blackbox #b_pack", function() 17describe("LuaRocks pack #blackbox #b_pack", function()
18 18
19 before_each(function() 19 before_each(function()
20 test_env.setup_specs(extra_rocks) 20 test_env.setup_specs(extra_rocks)
21 end) 21 end)
22 22
23 it("LuaRocks pack with no flags/arguments", function() 23 it("with no flags/arguments", function()
24 assert.is_false(run.luarocks_bool("pack")) 24 assert.is_false(run.luarocks_bool("pack"))
25 end) 25 end)
26 26
27 it("LuaRocks pack basic", function() 27 it("basic", function()
28 assert.is_true(run.luarocks_bool("pack luacov")) 28 assert(run.luarocks_bool("pack luacov"))
29 assert.is_true(test_env.remove_files(lfs.currentdir(), "luacov%-")) 29 assert(test_env.remove_files(lfs.currentdir(), "luacov%-"))
30 end) 30 end)
31 31
32 it("LuaRocks pack invalid rockspec", function() 32 it("invalid rockspec", function()
33 assert.is_false(run.luarocks_bool("pack " .. testing_paths.fixtures_dir .. "/invaild_validate-args-1.5.4-1.rockspec")) 33 assert.is_false(run.luarocks_bool("pack " .. testing_paths.fixtures_dir .. "/invalid_validate-args-1.5.4-1.rockspec"))
34 end) 34 end)
35 35
36 it("LuaRocks pack not installed rock", function() 36 it("not installed rock", function()
37 assert.is_false(run.luarocks_bool("pack cjson")) 37 assert.is_false(run.luarocks_bool("pack cjson"))
38 end) 38 end)
39 39
40 it("LuaRocks pack not installed rock from non existing manifest", function() 40 it("not installed rock from non existing manifest", function()
41 assert.is_false(run.luarocks_bool("pack /non/exist/temp.manif")) 41 assert.is_false(run.luarocks_bool("pack /non/exist/temp.manif"))
42 end) 42 end)
43 43
44 it("LuaRocks pack detects latest version version of rock", function() 44 it("detects latest version version of rock", function()
45 assert.is_true(run.luarocks_bool("install say 1.2")) 45 assert(run.luarocks_bool("install say 1.2"))
46 assert.is_true(run.luarocks_bool("install luassert")) 46 assert(run.luarocks_bool("install luassert"))
47 assert.is_true(run.luarocks_bool("install say 1.0")) 47 assert(run.luarocks_bool("install say 1.0"))
48 assert.is_true(run.luarocks_bool("pack say")) 48 assert(run.luarocks_bool("pack say"))
49 assert.is_truthy(lfs.attributes("say-1.2-1.all.rock")) 49 assert.is_truthy(lfs.attributes("say-1.2-1.all.rock"))
50 assert.is_true(test_env.remove_files(lfs.currentdir(), "say%-")) 50 assert(test_env.remove_files(lfs.currentdir(), "say%-"))
51 end) 51 end)
52 52
53 it("LuaRocks pack src", function() 53 it("src", function()
54 assert.is_true(run.luarocks_bool("install luasec " .. test_env.OPENSSL_DIRS)) 54 assert(run.luarocks_bool("install luasec " .. test_env.OPENSSL_DIRS))
55 assert.is_true(run.luarocks_bool("download --rockspec luasocket 3.0rc1-2")) 55 assert(run.luarocks_bool("download --rockspec luasocket 3.0rc1-2"))
56 assert.is_true(run.luarocks_bool("pack luasocket-3.0rc1-2.rockspec")) 56 assert(run.luarocks_bool("pack luasocket-3.0rc1-2.rockspec"))
57 assert.is_true(test_env.remove_files(lfs.currentdir(), "luasocket%-")) 57 assert(test_env.remove_files(lfs.currentdir(), "luasocket%-"))
58 end) 58 end)
59
60 describe("#mock namespaced dependencies", function()
61
62 setup(function()
63 test_env.mock_server_init()
64 end)
65
66 teardown(function()
67 test_env.mock_server_done()
68 end)
69
70 it("can pack rockspec with namespaced dependencies", function()
71 finally(function()
72 os.remove("has_namespaced_dep-1.0-1.src.rock")
73 end)
74 assert(run.luarocks_bool("pack " .. testing_paths.fixtures_dir .. "/a_repo/has_namespaced_dep-1.0-1.rockspec"))
75 assert.is_truthy(lfs.attributes("has_namespaced_dep-1.0-1.src.rock"))
76 end)
77 end)
78
79 describe("#namespaces", function()
80 it("packs a namespaced rock", function()
81 finally(function()
82 os.remove("a_rock-2.0-1.all.rock")
83 end)
84 assert(run.luarocks_bool("build a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" ))
85 assert(run.luarocks_bool("build a_rock --keep --server=" .. testing_paths.fixtures_dir .. "/a_repo" ))
86 assert(run.luarocks_bool("pack a_user/a_rock" ))
87 assert(lfs.attributes("a_rock-2.0-1.all.rock"))
88 end)
89 end)
90
59end) 91end)
60 92
61 93
diff --git a/spec/show_spec.lua b/spec/show_spec.lua
index d572be9b..234a8a33 100644
--- a/spec/show_spec.lua
+++ b/spec/show_spec.lua
@@ -30,7 +30,7 @@ describe("LuaRocks show tests #blackbox #b_show", function()
30 30
31 it("LuaRocks show modules of luacov", function() 31 it("LuaRocks show modules of luacov", function()
32 local output = run.luarocks("show --modules luacov") 32 local output = run.luarocks("show --modules luacov")
33 assert.is.truthy(output:match("luacovluacov.defaultsluacov.reporterluacov.reporter.defaultluacov.runnerluacov.statsluacov.tick")) 33 assert.match("luacov.*luacov.defaults.*luacov.reporter.*luacov.reporter.default.*luacov.runner.*luacov.stats.*luacov.tick", output)
34 end) 34 end)
35 35
36 it("LuaRocks show dependencies of luacov", function() 36 it("LuaRocks show dependencies of luacov", function()
diff --git a/spec/util/mock-server.lua b/spec/util/mock-server.lua
index 77d32927..30586c98 100644
--- a/spec/util/mock-server.lua
+++ b/spec/util/mock-server.lua
@@ -70,7 +70,8 @@ server:add_resource("/file/{name:[^/]+}", {
70 path = "/", 70 path = "/",
71 produces = "text/plain", 71 produces = "text/plain",
72 handler = function(query, name) 72 handler = function(query, name)
73 local fd = io.open("../spec/fixtures/"..name, "r") 73 local basedir = arg[1] or "../spec/fixtures"
74 local fd = io.open(basedir .. "/" .. name, "r")
74 if not fd then 75 if not fd then
75 return restserver.response():status(404) 76 return restserver.response():status(404)
76 end 77 end
diff --git a/spec/util/test_env.lua b/spec/util/test_env.lua
index 23ca5c77..94008913 100644
--- a/spec/util/test_env.lua
+++ b/spec/util/test_env.lua
@@ -175,7 +175,7 @@ local function execute_output(command, print_command, env_variables)
175 local file = assert(io.popen(command)) 175 local file = assert(io.popen(command))
176 local output = file:read('*all') 176 local output = file:read('*all')
177 file:close() 177 file:close()
178 return output:gsub("\n","") -- output adding new line, need to be removed 178 return (output:gsub("\r\n", "\n"):gsub("\n$", "")) -- remove final newline
179end 179end
180 180
181--- Set test_env.LUA_V or test_env.LUAJIT_V based 181--- Set test_env.LUA_V or test_env.LUAJIT_V based
diff --git a/spec/write_rockspec_spec.lua b/spec/write_rockspec_spec.lua
index e4a7fa73..0a0988d0 100644
--- a/spec/write_rockspec_spec.lua
+++ b/spec/write_rockspec_spec.lua
@@ -42,27 +42,27 @@ describe("LuaRocks write_rockspec tests #blackbox #b_write_rockspec", function()
42 42
43 it("runs", function() 43 it("runs", function()
44 finally(function() os.remove("testrock-dev-1.rockspec") end) 44 finally(function() os.remove("testrock-dev-1.rockspec") end)
45 assert.is_true(run.luarocks_bool("write_rockspec git://localhost:20000/testrock")) 45 assert.is_true(run.luarocks_bool("write_rockspec git://localhost/testrock"))
46 assert.is.truthy(lfs.attributes("testrock-dev-1.rockspec")) 46 assert.is.truthy(lfs.attributes("testrock-dev-1.rockspec"))
47 end) 47 end)
48 48
49 it("runs with --tag", function() 49 it("runs with --tag", function()
50 finally(function() os.remove("testrock-2.3.0-1.rockspec") end) 50 finally(function() os.remove("testrock-2.3.0-1.rockspec") end)
51 assert.is_true(run.luarocks_bool("write_rockspec git://localhost:20000/testrock --tag=v2.3.0")) 51 assert.is_true(run.luarocks_bool("write_rockspec git://localhost/testrock --tag=v2.3.0"))
52 assert.is.truthy(lfs.attributes("testrock-2.3.0-1.rockspec")) 52 assert.is.truthy(lfs.attributes("testrock-2.3.0-1.rockspec"))
53 -- TODO check contents 53 -- TODO check contents
54 end) 54 end)
55 55
56 it("runs with format flag", function() 56 it("runs with format flag", function()
57 finally(function() os.remove("testrock-dev-1.rockspec") end) 57 finally(function() os.remove("testrock-dev-1.rockspec") end)
58 assert.is_true(run.luarocks_bool("write_rockspec git://localhost:20000/testrock --rockspec-format=1.1 --lua-version=5.1,5.2")) 58 assert.is_true(run.luarocks_bool("write_rockspec git://localhost/testrock --rockspec-format=1.1 --lua-version=5.1,5.2"))
59 assert.is.truthy(lfs.attributes("testrock-dev-1.rockspec")) 59 assert.is.truthy(lfs.attributes("testrock-dev-1.rockspec"))
60 -- TODO check contents 60 -- TODO check contents
61 end) 61 end)
62 62
63 it("runs with full flags", function() 63 it("runs with full flags", function()
64 finally(function() os.remove("testrock-dev-1.rockspec") end) 64 finally(function() os.remove("testrock-dev-1.rockspec") end)
65 assert.is_true(run.luarocks_bool("write_rockspec git://localhost:20000/testrock --lua-version=5.1,5.2 --license=\"MIT/X11\" " 65 assert.is_true(run.luarocks_bool("write_rockspec git://localhost/testrock --lua-version=5.1,5.2 --license=\"MIT/X11\" "
66 .. " --homepage=\"http://www.luarocks.org\" --summary=\"A package manager for Lua modules\" ")) 66 .. " --homepage=\"http://www.luarocks.org\" --summary=\"A package manager for Lua modules\" "))
67 assert.is.truthy(lfs.attributes("testrock-dev-1.rockspec")) 67 assert.is.truthy(lfs.attributes("testrock-dev-1.rockspec"))
68 -- TODO check contents 68 -- TODO check contents
@@ -70,7 +70,7 @@ describe("LuaRocks write_rockspec tests #blackbox #b_write_rockspec", function()
70 70
71 it("with various flags", function() 71 it("with various flags", function()
72 finally(function() os.remove("testrock-dev-1.rockspec") end) 72 finally(function() os.remove("testrock-dev-1.rockspec") end)
73 assert.is_true(run.luarocks_bool("write_rockspec git://localhost:20000/testrock --lib=fcgi --license=\"3-clause BSD\" " .. "--lua-version=5.1,5.2")) 73 assert.is_true(run.luarocks_bool("write_rockspec git://localhost/testrock --lib=fcgi --license=\"3-clause BSD\" " .. "--lua-version=5.1,5.2"))
74 assert.is.truthy(lfs.attributes("testrock-dev-1.rockspec")) 74 assert.is.truthy(lfs.attributes("testrock-dev-1.rockspec"))
75 -- TODO check contents 75 -- TODO check contents
76 end) 76 end)
diff --git a/src/luarocks/admin/index.lua b/src/luarocks/admin/index.lua
index 80371151..76795104 100644
--- a/src/luarocks/admin/index.lua
+++ b/src/luarocks/admin/index.lua
@@ -4,7 +4,7 @@ local index = {}
4 4
5local util = require("luarocks.util") 5local util = require("luarocks.util")
6local fs = require("luarocks.fs") 6local fs = require("luarocks.fs")
7local vers = require("luarocks.vers") 7local vers = require("luarocks.core.vers")
8local persist = require("luarocks.persist") 8local persist = require("luarocks.persist")
9local dir = require("luarocks.dir") 9local dir = require("luarocks.dir")
10local manif = require("luarocks.manif") 10local manif = require("luarocks.manif")
diff --git a/src/luarocks/build.lua b/src/luarocks/build.lua
index e2419e55..c08fa6c6 100644
--- a/src/luarocks/build.lua
+++ b/src/luarocks/build.lua
@@ -156,11 +156,13 @@ end
156-- "all" for all trees, "order" for all trees with priority >= the current default, 156-- "all" for all trees, "order" for all trees with priority >= the current default,
157-- "none" for no trees. 157-- "none" for no trees.
158-- @param build_only_deps boolean: true to build the listed dependencies only. 158-- @param build_only_deps boolean: true to build the listed dependencies only.
159-- @param namespace string?: a namespace for the rockspec
159-- @return (string, string) or (nil, string, [string]): Name and version of 160-- @return (string, string) or (nil, string, [string]): Name and version of
160-- installed rock if succeeded or nil and an error message followed by an error code. 161-- installed rock if succeeded or nil and an error message followed by an error code.
161function build.build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_mode, build_only_deps) 162function build.build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_mode, build_only_deps, namespace)
162 assert(type(rockspec_file) == "string") 163 assert(type(rockspec_file) == "string")
163 assert(type(need_to_fetch) == "boolean") 164 assert(type(need_to_fetch) == "boolean")
165 assert(type(namespace) == "string" or not namespace)
164 166
165 local rockspec, err, errcode = fetch.load_rockspec(rockspec_file) 167 local rockspec, err, errcode = fetch.load_rockspec(rockspec_file)
166 if err then 168 if err then
@@ -319,6 +321,9 @@ function build.build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_m
319 ok, err = writer.make_rock_manifest(name, version) 321 ok, err = writer.make_rock_manifest(name, version)
320 if err then return nil, err end 322 if err then return nil, err end
321 323
324 ok, err = writer.make_namespace_file(name, version, namespace)
325 if err then return nil, err end
326
322 ok, err = repos.deploy_files(name, version, repos.should_wrap_bin_scripts(rockspec), deps_mode) 327 ok, err = repos.deploy_files(name, version, repos.should_wrap_bin_scripts(rockspec), deps_mode)
323 if err then return nil, err end 328 if err then return nil, err end
324 329
diff --git a/src/luarocks/cmd/build.lua b/src/luarocks/cmd/build.lua
index 0d969ff6..1b5c8fdc 100644
--- a/src/luarocks/cmd/build.lua
+++ b/src/luarocks/cmd/build.lua
@@ -14,6 +14,7 @@ local remove = require("luarocks.remove")
14local cfg = require("luarocks.core.cfg") 14local cfg = require("luarocks.core.cfg")
15local build = require("luarocks.build") 15local build = require("luarocks.build")
16local writer = require("luarocks.manif.writer") 16local writer = require("luarocks.manif.writer")
17local search = require("luarocks.search")
17 18
18cmd_build.help_summary = "build/compile a rock." 19cmd_build.help_summary = "build/compile a rock."
19cmd_build.help_arguments = "[--pack-binary-rock] [--keep] {<rockspec>|<rock>|<name> [<version>]}" 20cmd_build.help_arguments = "[--pack-binary-rock] [--keep] {<rockspec>|<rock>|<name> [<version>]}"
@@ -47,9 +48,10 @@ or the name of a rock to be fetched from a repository.
47-- "one" for the current default tree, "all" for all trees, 48-- "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-- "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-- @param build_only_deps boolean: true to build the listed dependencies only.
51-- @param namespace string?: an optional namespace
50-- @return boolean or (nil, string, [string]): True if build was successful, 52-- @return boolean or (nil, string, [string]): True if build was successful,
51-- or false and an error message and an optional error code. 53-- or false and an error message and an optional error code.
52local function build_rock(rock_file, need_to_fetch, deps_mode, build_only_deps) 54local function build_rock(rock_file, need_to_fetch, deps_mode, build_only_deps, namespace)
53 assert(type(rock_file) == "string") 55 assert(type(rock_file) == "string")
54 assert(type(need_to_fetch) == "boolean") 56 assert(type(need_to_fetch) == "boolean")
55 57
@@ -62,25 +64,29 @@ local function build_rock(rock_file, need_to_fetch, deps_mode, build_only_deps)
62 local rockspec_file = path.rockspec_name_from_rock(rock_file) 64 local rockspec_file = path.rockspec_name_from_rock(rock_file)
63 ok, err = fs.change_dir(unpack_dir) 65 ok, err = fs.change_dir(unpack_dir)
64 if not ok then return nil, err end 66 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) 67 ok, err, errcode = build.build_rockspec(rockspec_file, need_to_fetch, false, deps_mode, build_only_deps, namespace)
66 fs.pop_dir() 68 fs.pop_dir()
67 return ok, err, errcode 69 return ok, err, errcode
68end 70end
69 71
70local function do_build(name, version, deps_mode, build_only_deps) 72local function build_file(filename, namespace, deps_mode, build_only_deps)
71 if name:match("%.rockspec$") then 73 if filename:match("%.rockspec$") then
72 return build.build_rockspec(name, true, false, deps_mode, build_only_deps) 74 return build.build_rockspec(filename, true, false, deps_mode, build_only_deps, namespace)
73 elseif name:match("%.src%.rock$") then 75 elseif filename:match("%.src%.rock$") then
74 return build_rock(name, false, deps_mode, build_only_deps) 76 return build_rock(filename, false, deps_mode, build_only_deps, namespace)
75 elseif name:match("%.all%.rock$") then 77 elseif filename:match("%.all%.rock$") then
76 return build_rock(name, true, deps_mode, build_only_deps) 78 return build_rock(filename, true, deps_mode, build_only_deps, namespace)
77 elseif name:match("%.rock$") then 79 elseif filename:match("%.rock$") then
78 return build_rock(name, true, deps_mode, build_only_deps) 80 return build_rock(filename, true, deps_mode, build_only_deps, namespace)
79 elseif not name:match("/") then 81 end
80 local search = require("luarocks.search") 82end
81 return search.act_on_src_or_rockspec(do_build, name:lower(), version, nil, deps_mode, build_only_deps) 83
84local function do_build(name, version, namespace, deps_mode, build_only_deps)
85 if name:match("%.rockspec$") or name:match("%.rock$") then
86 return build_file(name, namespace, deps_mode, build_only_deps)
87 else
88 return search.act_on_src_or_rockspec(build_file, name, version, deps_mode, build_only_deps)
82 end 89 end
83 return nil, "Don't know what to do with "..name
84end 90end
85 91
86--- Driver function for "build" command. 92--- Driver function for "build" command.
@@ -97,16 +103,22 @@ function cmd_build.command(flags, name, version)
97 end 103 end
98 assert(type(version) == "string" or not version) 104 assert(type(version) == "string" or not version)
99 105
106 name = util.adjust_name_and_namespace(name, flags)
107 local deps_mode = deps.get_deps_mode(flags)
108 local namespace = flags["namespace"]
109 local build_only_deps = flags["only-deps"]
110
100 if flags["pack-binary-rock"] then 111 if flags["pack-binary-rock"] then
101 return pack.pack_binary_rock(name, version, do_build, name, version, deps.get_deps_mode(flags)) 112 return pack.pack_binary_rock(name, version, function() return do_build(name, version, namespace, deps_mode) end)
102 else 113 else
103 local ok, err = fs.check_command_permissions(flags) 114 local ok, err = fs.check_command_permissions(flags)
104 if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end 115 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"]) 116
117 ok, err = do_build(name, version, namespace, deps_mode, build_only_deps)
106 if not ok then return nil, err end 118 if not ok then return nil, err end
107 name, version = ok, err 119 name, version = ok, err
108 120
109 if (not flags["only-deps"]) and (not flags["keep"]) and not cfg.keep_other_versions then 121 if (not build_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"]) 122 local ok, err = remove.remove_other_versions(name, version, flags["force"], flags["force-fast"])
111 if not ok then util.printerr(err) end 123 if not ok then util.printerr(err) end
112 end 124 end
diff --git a/src/luarocks/cmd/doc.lua b/src/luarocks/cmd/doc.lua
index 5d521276..a2472be4 100644
--- a/src/luarocks/cmd/doc.lua
+++ b/src/luarocks/cmd/doc.lua
@@ -4,6 +4,7 @@
4local doc = {} 4local doc = {}
5 5
6local util = require("luarocks.util") 6local util = require("luarocks.util")
7local queries = require("luarocks.queries")
7local search = require("luarocks.search") 8local search = require("luarocks.search")
8local path = require("luarocks.path") 9local path = require("luarocks.path")
9local dir = require("luarocks.dir") 10local dir = require("luarocks.dir")
@@ -61,9 +62,9 @@ function doc.command(flags, name, version)
61 return nil, "Argument missing. "..util.see_help("doc") 62 return nil, "Argument missing. "..util.see_help("doc")
62 end 63 end
63 64
64 name = name:lower() 65 name = util.adjust_name_and_namespace(name, flags)
65 66 local query = queries.new(name, version)
66 local iname, iversion, repo = search.pick_installed_rock(name, version, flags["tree"]) 67 local iname, iversion, repo = search.pick_installed_rock(query, flags["tree"])
67 if not iname then 68 if not iname then
68 util.printout(name..(version and " "..version or "").." is not installed. Looking for it in the rocks servers...") 69 util.printout(name..(version and " "..version or "").." is not installed. Looking for it in the rocks servers...")
69 return try_to_open_homepage(name, version) 70 return try_to_open_homepage(name, version)
@@ -78,7 +79,7 @@ function doc.command(flags, name, version)
78 return show_homepage(descript.homepage, name, version) 79 return show_homepage(descript.homepage, name, version)
79 end 80 end
80 81
81 local directory = path.install_dir(name,version,repo) 82 local directory = path.install_dir(name, version, repo)
82 83
83 local docdir 84 local docdir
84 local directories = { "doc", "docs" } 85 local directories = { "doc", "docs" }
diff --git a/src/luarocks/cmd/download.lua b/src/luarocks/cmd/download.lua
index 9c119f6e..50c10c0c 100644
--- a/src/luarocks/cmd/download.lua
+++ b/src/luarocks/cmd/download.lua
@@ -26,6 +26,9 @@ function cmd_download.command(flags, name, version)
26 if type(name) ~= "string" and not flags["all"] then 26 if type(name) ~= "string" and not flags["all"] then
27 return nil, "Argument missing. "..util.see_help("download") 27 return nil, "Argument missing. "..util.see_help("download")
28 end 28 end
29
30 name = util.adjust_name_and_namespace(name, flags)
31
29 if not name then name, version = "", "" end 32 if not name then name, version = "", "" end
30 33
31 local arch 34 local arch
diff --git a/src/luarocks/cmd/install.lua b/src/luarocks/cmd/install.lua
index 6901a680..80fc4d27 100644
--- a/src/luarocks/cmd/install.lua
+++ b/src/luarocks/cmd/install.lua
@@ -12,6 +12,7 @@ local writer = require("luarocks.manif.writer")
12local remove = require("luarocks.remove") 12local remove = require("luarocks.remove")
13local search = require("luarocks.search") 13local search = require("luarocks.search")
14local queries = require("luarocks.queries") 14local queries = require("luarocks.queries")
15local vers = require("luarocks.core.vers")
15local cfg = require("luarocks.core.cfg") 16local cfg = require("luarocks.core.cfg")
16 17
17install.help_summary = "Install a rock." 18install.help_summary = "Install a rock."
@@ -36,10 +37,13 @@ or a filename of a locally available rock.
36-- @param deps_mode: string: Which trees to check dependencies for: 37-- @param deps_mode: string: Which trees to check dependencies for:
37-- "one" for the current default tree, "all" for all trees, 38-- "one" for the current default tree, "all" for all trees,
38-- "order" for all trees with priority >= the current default, "none" for no trees. 39-- "order" for all trees with priority >= the current default, "none" for no trees.
40-- @param namespace: string?: an optional namespace.
39-- @return (string, string) or (nil, string, [string]): Name and version of 41-- @return (string, string) or (nil, string, [string]): Name and version of
40-- installed rock if succeeded or nil and an error message followed by an error code. 42-- installed rock if succeeded or nil and an error message followed by an error code.
41function install.install_binary_rock(rock_file, deps_mode) 43function install.install_binary_rock(rock_file, deps_mode, namespace)
42 assert(type(rock_file) == "string") 44 assert(type(rock_file) == "string")
45 assert(type(deps_mode) == "string")
46 assert(type(namespace) == "string" or namespace == nil)
43 47
44 local name, version, arch = path.parse_name(rock_file) 48 local name, version, arch = path.parse_name(rock_file)
45 if not name then 49 if not name then
@@ -79,6 +83,11 @@ function install.install_binary_rock(rock_file, deps_mode)
79 if err then return nil, err end 83 if err then return nil, err end
80 end 84 end
81 85
86 if namespace then
87 ok, err = writer.make_namespace_file(name, version, namespace)
88 if err then return nil, err end
89 end
90
82 if deps_mode ~= "none" then 91 if deps_mode ~= "none" then
83 ok, err, errcode = deps.fulfill_dependencies(rockspec, deps_mode) 92 ok, err, errcode = deps.fulfill_dependencies(rockspec, deps_mode)
84 if err then return nil, err, errcode end 93 if err then return nil, err, errcode end
@@ -137,6 +146,34 @@ function install.install_binary_rock_deps(rock_file, deps_mode)
137 return name, version 146 return name, version
138end 147end
139 148
149local function install_rock_file_deps(filename, deps_mode)
150 local name, version = install.install_binary_rock_deps(filename, deps_mode)
151 if not name then return nil, version end
152
153 writer.check_dependencies(nil, deps_mode)
154 return name, version
155end
156
157local function install_rock_file(filename, namespace, deps_mode, keep, force, force_fast)
158 assert(type(filename) == "string")
159 assert(type(namespace) == "string" or namespace == nil)
160 assert(type(deps_mode) == "string")
161 assert(type(keep) == "boolean" or keep == nil)
162 assert(type(force) == "boolean" or force == nil)
163 assert(type(force_fast) == "boolean" or force_fast == nil)
164
165 local name, version = install.install_binary_rock(filename, deps_mode, namespace)
166 if not name then return nil, version end
167
168 if (not keep) and not cfg.keep_other_versions then
169 local ok, err = remove.remove_other_versions(name, version, force, force_fast)
170 if not ok then util.printerr(err) end
171 end
172
173 writer.check_dependencies(nil, deps_mode)
174 return name, version
175end
176
140--- Driver function for the "install" command. 177--- Driver function for the "install" command.
141-- @param name string: name of a binary rock. If an URL or pathname 178-- @param name string: name of a binary rock. If an URL or pathname
142-- to a binary rock is given, fetches and installs it. If a rockspec or a 179-- to a binary rock is given, fetches and installs it. If a rockspec or a
@@ -152,6 +189,8 @@ function install.command(flags, name, version)
152 return nil, "Argument missing. "..util.see_help("install") 189 return nil, "Argument missing. "..util.see_help("install")
153 end 190 end
154 191
192 name = util.adjust_name_and_namespace(name, flags)
193
155 local ok, err = fs.check_command_permissions(flags) 194 local ok, err = fs.check_command_permissions(flags)
156 if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end 195 if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end
157 196
@@ -159,21 +198,12 @@ function install.command(flags, name, version)
159 local build = require("luarocks.cmd.build") 198 local build = require("luarocks.cmd.build")
160 return build.command(flags, name) 199 return build.command(flags, name)
161 elseif name:match("%.rock$") then 200 elseif name:match("%.rock$") then
201 local deps_mode = deps.get_deps_mode(flags)
162 if flags["only-deps"] then 202 if flags["only-deps"] then
163 ok, err = install.install_binary_rock_deps(name, deps.get_deps_mode(flags)) 203 return install_rock_file_deps(name, deps_mode)
164 else 204 else
165 ok, err = install.install_binary_rock(name, deps.get_deps_mode(flags)) 205 return install_rock_file(name, flags["namespace"], deps_mode, flags["keep"], flags["force"], flags["force-fast"])
166 end
167 if not ok then return nil, err end
168 name, version = ok, err
169
170 if (not flags["only-deps"]) and (not flags["keep"]) and not cfg.keep_other_versions then
171 local ok, err = remove.remove_other_versions(name, version, flags["force"], flags["force-fast"])
172 if not ok then util.printerr(err) end
173 end 206 end
174
175 writer.check_dependencies(nil, deps.get_deps_mode(flags))
176 return name, version
177 else 207 else
178 local url, err = search.find_suitable_rock(queries.new(name:lower(), version)) 208 local url, err = search.find_suitable_rock(queries.new(name:lower(), version))
179 if not url then 209 if not url then
diff --git a/src/luarocks/cmd/list.lua b/src/luarocks/cmd/list.lua
index e07c4ff3..102a08f0 100644
--- a/src/luarocks/cmd/list.lua
+++ b/src/luarocks/cmd/list.lua
@@ -5,7 +5,7 @@ local list = {}
5 5
6local search = require("luarocks.search") 6local search = require("luarocks.search")
7local queries = require("luarocks.queries") 7local queries = require("luarocks.queries")
8local vers = require("luarocks.vers") 8local vers = require("luarocks.core.vers")
9local cfg = require("luarocks.core.cfg") 9local cfg = require("luarocks.core.cfg")
10local util = require("luarocks.util") 10local util = require("luarocks.util")
11local path = require("luarocks.path") 11local path = require("luarocks.path")
@@ -24,7 +24,7 @@ list.help = [[
24local function check_outdated(trees, query) 24local function check_outdated(trees, query)
25 local results_installed = {} 25 local results_installed = {}
26 for _, tree in ipairs(trees) do 26 for _, tree in ipairs(trees) do
27 search.manifest_search(results_installed, path.rocks_dir(tree), query) 27 search.local_manifest_search(results_installed, path.rocks_dir(tree), query)
28 end 28 end
29 local outdated = {} 29 local outdated = {}
30 for name, versions in util.sortedpairs(results_installed) do 30 for name, versions in util.sortedpairs(results_installed) do
@@ -32,7 +32,7 @@ local function check_outdated(trees, query)
32 table.sort(versions, vers.compare_versions) 32 table.sort(versions, vers.compare_versions)
33 local latest_installed = versions[1] 33 local latest_installed = versions[1]
34 34
35 local query_available = queries.new(name:lower(), nil, false) 35 local query_available = queries.new(name:lower())
36 local results_available, err = search.search_repos(query_available) 36 local results_available, err = search.search_repos(query_available)
37 37
38 if results_available[name] then 38 if results_available[name] then
@@ -81,13 +81,13 @@ function list.command(flags, filter, version)
81 81
82 local results = {} 82 local results = {}
83 for _, tree in ipairs(trees) do 83 for _, tree in ipairs(trees) do
84 local ok, err, errcode = search.manifest_search(results, path.rocks_dir(tree), query) 84 local ok, err, errcode = search.local_manifest_search(results, path.rocks_dir(tree), query)
85 if not ok and errcode ~= "open" then 85 if not ok and errcode ~= "open" then
86 util.warning(err) 86 util.warning(err)
87 end 87 end
88 end 88 end
89 util.title("Installed rocks for Lua "..cfg.lua_version..":", flags["porcelain"]) 89 util.title("Installed rocks for Lua "..cfg.lua_version..":", flags["porcelain"])
90 search.print_results(results, flags["porcelain"]) 90 search.print_result_tree(results, flags["porcelain"])
91 return true 91 return true
92end 92end
93 93
diff --git a/src/luarocks/cmd/make.lua b/src/luarocks/cmd/make.lua
index 8f01856e..850da6f4 100644
--- a/src/luarocks/cmd/make.lua
+++ b/src/luarocks/cmd/make.lua
@@ -72,7 +72,7 @@ function make.command(flags, rockspec)
72 if not rspec then 72 if not rspec then
73 return nil, err 73 return nil, err
74 end 74 end
75 return pack.pack_binary_rock(rspec.name, rspec.version, build.build_rockspec, rockspec, false, true, deps.get_deps_mode(flags)) 75 return pack.pack_binary_rock(rspec.name, rspec.version, function() return build.build_rockspec(rockspec, false, true, deps.get_deps_mode(flags)) end)
76 else 76 else
77 local ok, err = fs.check_command_permissions(flags) 77 local ok, err = fs.check_command_permissions(flags)
78 if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end 78 if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end
diff --git a/src/luarocks/cmd/pack.lua b/src/luarocks/cmd/pack.lua
index e43e5b3f..3d3cdef5 100644
--- a/src/luarocks/cmd/pack.lua
+++ b/src/luarocks/cmd/pack.lua
@@ -32,7 +32,8 @@ function cmd_pack.command(flags, arg, version)
32 if arg:match(".*%.rockspec") then 32 if arg:match(".*%.rockspec") then
33 file, err = pack.pack_source_rock(arg) 33 file, err = pack.pack_source_rock(arg)
34 else 34 else
35 file, err = pack.pack_installed_rock(arg:lower(), version, flags["tree"]) 35 local name = util.adjust_name_and_namespace(arg, flags)
36 file, err = pack.pack_installed_rock(name, version, flags["tree"])
36 end 37 end
37 if err then 38 if err then
38 return nil, err 39 return nil, err
diff --git a/src/luarocks/cmd/purge.lua b/src/luarocks/cmd/purge.lua
index 15efb0ef..5f868e60 100644
--- a/src/luarocks/cmd/purge.lua
+++ b/src/luarocks/cmd/purge.lua
@@ -7,7 +7,7 @@ local util = require("luarocks.util")
7local fs = require("luarocks.fs") 7local fs = require("luarocks.fs")
8local path = require("luarocks.path") 8local path = require("luarocks.path")
9local search = require("luarocks.search") 9local search = require("luarocks.search")
10local vers = require("luarocks.vers") 10local vers = require("luarocks.core.vers")
11local repos = require("luarocks.repos") 11local repos = require("luarocks.repos")
12local writer = require("luarocks.manif.writer") 12local writer = require("luarocks.manif.writer")
13local cfg = require("luarocks.core.cfg") 13local cfg = require("luarocks.core.cfg")
@@ -45,7 +45,7 @@ function purge.command(flags)
45 local ok, err = fs.check_command_permissions(flags) 45 local ok, err = fs.check_command_permissions(flags)
46 if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end 46 if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end
47 47
48 search.manifest_search(results, path.rocks_dir(tree), queries.all()) 48 search.local_manifest_search(results, path.rocks_dir(tree), queries.all())
49 49
50 local sort = function(a,b) return vers.compare_versions(b,a) end 50 local sort = function(a,b) return vers.compare_versions(b,a) end
51 if flags["old-versions"] then 51 if flags["old-versions"] then
diff --git a/src/luarocks/cmd/remove.lua b/src/luarocks/cmd/remove.lua
index 2624854d..4af036aa 100644
--- a/src/luarocks/cmd/remove.lua
+++ b/src/luarocks/cmd/remove.lua
@@ -36,6 +36,8 @@ function cmd_remove.command(flags, name, version)
36 if type(name) ~= "string" then 36 if type(name) ~= "string" then
37 return nil, "Argument missing. "..util.see_help("remove") 37 return nil, "Argument missing. "..util.see_help("remove")
38 end 38 end
39
40 name = util.adjust_name_and_namespace(name, flags)
39 41
40 local deps_mode = flags["deps-mode"] or cfg.deps_mode 42 local deps_mode = flags["deps-mode"] or cfg.deps_mode
41 43
@@ -51,7 +53,7 @@ function cmd_remove.command(flags, name, version)
51 53
52 local results = {} 54 local results = {}
53 name = name:lower() 55 name = name:lower()
54 search.manifest_search(results, cfg.rocks_dir, queries.new(name, version)) 56 search.local_manifest_search(results, cfg.rocks_dir, queries.new(name, version))
55 if not results[name] then 57 if not results[name] then
56 return nil, "Could not find rock '"..name..(version and " "..version or "").."' in "..path.rocks_tree_to_string(cfg.root_dir) 58 return nil, "Could not find rock '"..name..(version and " "..version or "").."' in "..path.rocks_tree_to_string(cfg.root_dir)
57 end 59 end
diff --git a/src/luarocks/cmd/search.lua b/src/luarocks/cmd/search.lua
index ccdbda7b..8f4d014e 100644
--- a/src/luarocks/cmd/search.lua
+++ b/src/luarocks/cmd/search.lua
@@ -7,6 +7,7 @@ local cfg = require("luarocks.core.cfg")
7local util = require("luarocks.util") 7local util = require("luarocks.util")
8local search = require("luarocks.search") 8local search = require("luarocks.search")
9local queries = require("luarocks.queries") 9local queries = require("luarocks.queries")
10local results = require("luarocks.results")
10 11
11cmd_search.help_summary = "Query the LuaRocks servers." 12cmd_search.help_summary = "Query the LuaRocks servers."
12cmd_search.help_arguments = "[--source] [--binary] { <name> [<version>] | --all }" 13cmd_search.help_arguments = "[--source] [--binary] { <name> [<version>] | --all }"
@@ -23,19 +24,20 @@ cmd_search.help = [[
23--- Splits a list of search results into two lists, one for "source" results 24--- Splits a list of search results into two lists, one for "source" results
24-- to be used with the "build" command, and one for "binary" results to be 25-- to be used with the "build" command, and one for "binary" results to be
25-- used with the "install" command. 26-- used with the "install" command.
26-- @param results table: A search results table. 27-- @param result_tree table: A search results table.
27-- @return (table, table): Two tables, one for source and one for binary 28-- @return (table, table): Two tables, one for source and one for binary
28-- results. 29-- results.
29local function split_source_and_binary_results(results) 30local function split_source_and_binary_results(result_tree)
30 local sources, binaries = {}, {} 31 local sources, binaries = {}, {}
31 for name, versions in pairs(results) do 32 for name, versions in pairs(result_tree) do
32 for version, repositories in pairs(versions) do 33 for version, repositories in pairs(versions) do
33 for _, repo in ipairs(repositories) do 34 for _, repo in ipairs(repositories) do
34 local where = sources 35 local where = sources
35 if repo.arch == "all" or repo.arch == cfg.arch then 36 if repo.arch == "all" or repo.arch == cfg.arch then
36 where = binaries 37 where = binaries
37 end 38 end
38 search.store_result(where, name, version, repo.arch, repo.repo) 39 local entry = results.new(name, version, repo.repo, repo.arch)
40 search.store_result(where, entry)
39 end 41 end
40 end 42 end
41 end 43 end
@@ -48,6 +50,9 @@ end
48-- @return boolean or (nil, string): True if build was successful; nil and an 50-- @return boolean or (nil, string): True if build was successful; nil and an
49-- error message otherwise. 51-- error message otherwise.
50function cmd_search.command(flags, name, version) 52function cmd_search.command(flags, name, version)
53
54 name = util.adjust_name_and_namespace(name, flags)
55
51 if flags["all"] then 56 if flags["all"] then
52 name, version = "", nil 57 name, version = "", nil
53 end 58 end
@@ -57,18 +62,18 @@ function cmd_search.command(flags, name, version)
57 end 62 end
58 63
59 local query = queries.new(name:lower(), version, true) 64 local query = queries.new(name:lower(), version, true)
60 local results, err = search.search_repos(query) 65 local result_tree, err = search.search_repos(query)
61 local porcelain = flags["porcelain"] 66 local porcelain = flags["porcelain"]
62 local full_name = name .. (version and " " .. version or "") 67 local full_name = name .. (version and " " .. version or "")
63 util.title(full_name .. " - Search results for Lua "..cfg.lua_version..":", porcelain, "=") 68 util.title(full_name .. " - Search results for Lua "..cfg.lua_version..":", porcelain, "=")
64 local sources, binaries = split_source_and_binary_results(results) 69 local sources, binaries = split_source_and_binary_results(result_tree)
65 if next(sources) and not flags["binary"] then 70 if next(sources) and not flags["binary"] then
66 util.title("Rockspecs and source rocks:", porcelain) 71 util.title("Rockspecs and source rocks:", porcelain)
67 search.print_results(sources, porcelain) 72 search.print_result_tree(sources, porcelain)
68 end 73 end
69 if next(binaries) and not flags["source"] then 74 if next(binaries) and not flags["source"] then
70 util.title("Binary and pure-Lua rocks:", porcelain) 75 util.title("Binary and pure-Lua rocks:", porcelain)
71 search.print_results(binaries, porcelain) 76 search.print_result_tree(binaries, porcelain)
72 end 77 end
73 return true 78 return true
74end 79end
diff --git a/src/luarocks/cmd/show.lua b/src/luarocks/cmd/show.lua
index 21c75cf2..9f8bc472 100644
--- a/src/luarocks/cmd/show.lua
+++ b/src/luarocks/cmd/show.lua
@@ -2,11 +2,12 @@
2-- Shows information about an installed rock. 2-- Shows information about an installed rock.
3local show = {} 3local show = {}
4 4
5local queries = require("luarocks.queries")
5local search = require("luarocks.search") 6local search = require("luarocks.search")
6local cfg = require("luarocks.core.cfg") 7local cfg = require("luarocks.core.cfg")
7local util = require("luarocks.util") 8local util = require("luarocks.util")
8local path = require("luarocks.path") 9local path = require("luarocks.path")
9local vers = require("luarocks.vers") 10local vers = require("luarocks.core.vers")
10local fetch = require("luarocks.fetch") 11local fetch = require("luarocks.fetch")
11local manif = require("luarocks.manif") 12local manif = require("luarocks.manif")
12local repos = require("luarocks.repos") 13local repos = require("luarocks.repos")
@@ -57,12 +58,12 @@ local function format_text(text)
57 return (table.concat(paragraphs, "\n\n"):gsub("%s$", "")) 58 return (table.concat(paragraphs, "\n\n"):gsub("%s$", ""))
58end 59end
59 60
60local function installed_rock_label(name, tree) 61local function installed_rock_label(dep, tree)
61 local installed, version 62 local installed, version
62 if cfg.rocks_provided[name] then 63 if cfg.rocks_provided[dep.name] then
63 installed, version = true, cfg.rocks_provided[name] 64 installed, version = true, cfg.rocks_provided[dep.name]
64 else 65 else
65 installed, version = search.pick_installed_rock(name, nil, tree) 66 installed, version = search.pick_installed_rock(dep, tree)
66 end 67 end
67 return installed and "(using "..version..")" or "(missing)" 68 return installed and "(using "..version..")" or "(missing)"
68end 69end
@@ -81,14 +82,17 @@ function show.command(flags, name, version)
81 if not name then 82 if not name then
82 return nil, "Argument missing. "..util.see_help("show") 83 return nil, "Argument missing. "..util.see_help("show")
83 end 84 end
85
86 name = util.adjust_name_and_namespace(name, flags)
87 local query = queries.new(name, version)
84 88
85 local repo, repo_url 89 local repo, repo_url
86 name, version, repo, repo_url = search.pick_installed_rock(name:lower(), version, flags["tree"]) 90 name, version, repo, repo_url = search.pick_installed_rock(query, flags["tree"])
87 if not name then 91 if not name then
88 return nil, version 92 return nil, version
89 end 93 end
90 94
91 local directory = path.install_dir(name,version,repo) 95 local directory = path.install_dir(name, version, repo)
92 local rockspec_file = path.rockspec_file(name, version, repo) 96 local rockspec_file = path.rockspec_file(name, version, repo)
93 local rockspec, err = fetch.load_local_rockspec(rockspec_file) 97 local rockspec, err = fetch.load_local_rockspec(rockspec_file)
94 if not rockspec then return nil,err end 98 if not rockspec then return nil,err end
@@ -147,7 +151,7 @@ function show.command(flags, name, version)
147 util.printout("Depends on:") 151 util.printout("Depends on:")
148 for _, dep in ipairs(rockspec.dependencies) do 152 for _, dep in ipairs(rockspec.dependencies) do
149 direct_deps[dep.name] = true 153 direct_deps[dep.name] = true
150 util.printout("\t"..vers.show_dep(dep).." "..installed_rock_label(dep.name, flags["tree"])) 154 util.printout("\t"..tostring(dep).." "..installed_rock_label(dep, flags["tree"]))
151 end 155 end
152 end 156 end
153 local has_indirect_deps 157 local has_indirect_deps
diff --git a/src/luarocks/cmd/unpack.lua b/src/luarocks/cmd/unpack.lua
index c50701b0..f4232266 100644
--- a/src/luarocks/cmd/unpack.lua
+++ b/src/luarocks/cmd/unpack.lua
@@ -92,7 +92,7 @@ end
92-- @param file string: A rockspec or .rock URL. 92-- @param file string: A rockspec or .rock URL.
93-- @return boolean or (nil, string): true if successful or nil followed 93-- @return boolean or (nil, string): true if successful or nil followed
94-- by an error message. 94-- by an error message.
95local function run_unpacker(file, force) 95local function run_unpacker(file, namespace, force)
96 assert(type(file) == "string") 96 assert(type(file) == "string")
97 97
98 local base_name = dir.base_name(file) 98 local base_name = dir.base_name(file)
@@ -153,11 +153,13 @@ function unpack.command(flags, name, version)
153 return nil, "Argument missing. "..util.see_help("unpack") 153 return nil, "Argument missing. "..util.see_help("unpack")
154 end 154 end
155 155
156 name = util.adjust_name_and_namespace(name, flags)
157
156 if name:match(".*%.rock") or name:match(".*%.rockspec") then 158 if name:match(".*%.rock") or name:match(".*%.rockspec") then
157 return run_unpacker(name, flags["force"]) 159 return run_unpacker(name, flags["namespace"], flags["force"])
158 else 160 else
159 local search = require("luarocks.search") 161 local search = require("luarocks.search")
160 return search.act_on_src_or_rockspec(run_unpacker, name:lower(), version) 162 return search.act_on_src_or_rockspec(run_unpacker, name, version)
161 end 163 end
162end 164end
163 165
diff --git a/src/luarocks/cmd/write_rockspec.lua b/src/luarocks/cmd/write_rockspec.lua
index dc6eaab1..88223857 100644
--- a/src/luarocks/cmd/write_rockspec.lua
+++ b/src/luarocks/cmd/write_rockspec.lua
@@ -9,7 +9,7 @@ local path = require("luarocks.path")
9local persist = require("luarocks.persist") 9local persist = require("luarocks.persist")
10local type_rockspec = require("luarocks.type.rockspec") 10local type_rockspec = require("luarocks.type.rockspec")
11local util = require("luarocks.util") 11local util = require("luarocks.util")
12local vers = require("luarocks.vers") 12local vers = require("luarocks.core.vers")
13 13
14write_rockspec.help_summary = "Write a template for a rockspec file." 14write_rockspec.help_summary = "Write a template for a rockspec file."
15write_rockspec.help_arguments = "[--output=<file> ...] [<name>] [<version>] [<url>|<path>]" 15write_rockspec.help_arguments = "[--output=<file> ...] [<name>] [<version>] [<url>|<path>]"
@@ -227,6 +227,9 @@ local function rockspec_cleanup(rockspec)
227end 227end
228 228
229function write_rockspec.command(flags, name, version, url_or_dir) 229function write_rockspec.command(flags, name, version, url_or_dir)
230
231 name = util.adjust_name_and_namespace(name, flags)
232
230 if not name then 233 if not name then
231 url_or_dir = "." 234 url_or_dir = "."
232 elseif not version then 235 elseif not version then
@@ -286,7 +289,11 @@ function write_rockspec.command(flags, name, version, url_or_dir)
286 } 289 }
287 path.configure_paths(rockspec) 290 path.configure_paths(rockspec)
288 rockspec.source.protocol = protocol 291 rockspec.source.protocol = protocol
289 rockspec.format_is_at_least = vers.format_is_at_least 292
293 local parsed_format = vers.parse_version(rockspec.rockspec_format or "1.0")
294 rockspec.format_is_at_least = function(_, v)
295 return parsed_format >= vers.parse_version(v)
296 end
290 297
291 configure_lua_version(rockspec, flags["lua-version"]) 298 configure_lua_version(rockspec, flags["lua-version"])
292 299
diff --git a/src/luarocks/core/util.lua b/src/luarocks/core/util.lua
index 1a963a65..99fd1618 100644
--- a/src/luarocks/core/util.lua
+++ b/src/luarocks/core/util.lua
@@ -204,6 +204,12 @@ function util.printerr(...)
204 io.stderr:write("\n") 204 io.stderr:write("\n")
205end 205end
206 206
207--- Display a warning message.
208-- @param msg string: the warning message
209function util.warning(msg)
210 util.printerr("Warning: "..msg)
211end
212
207--- Simple sort function used as a default for util.sortedpairs. 213--- Simple sort function used as a default for util.sortedpairs.
208local function default_sort(a, b) 214local function default_sort(a, b)
209 local ta = type(a) 215 local ta = type(a)
diff --git a/src/luarocks/deps.lua b/src/luarocks/deps.lua
index 229c3843..182bbfb2 100644
--- a/src/luarocks/deps.lua
+++ b/src/luarocks/deps.lua
@@ -7,7 +7,7 @@ local manif = require("luarocks.manif")
7local path = require("luarocks.path") 7local path = require("luarocks.path")
8local dir = require("luarocks.dir") 8local dir = require("luarocks.dir")
9local util = require("luarocks.util") 9local util = require("luarocks.util")
10local vers = require("luarocks.vers") 10local vers = require("luarocks.core.vers")
11local queries = require("luarocks.queries") 11local queries = require("luarocks.queries")
12 12
13--- Attempt to match a dependency to an installed rock. 13--- Attempt to match a dependency to an installed rock.
@@ -28,7 +28,7 @@ local function match_dep(dep, blacklist, deps_mode, rocks_provided)
28 -- Provided rocks have higher priority than manifest's rocks. 28 -- Provided rocks have higher priority than manifest's rocks.
29 versions = { provided } 29 versions = { provided }
30 else 30 else
31 versions = manif.get_versions(dep.name, deps_mode) 31 versions = manif.get_versions(dep, deps_mode)
32 end 32 end
33 33
34 local latest_version 34 local latest_version
@@ -115,7 +115,7 @@ function deps.report_missing_dependencies(name, version, dependencies, deps_mode
115 first_missing_dep = false 115 first_missing_dep = false
116 end 116 end
117 117
118 util.printout((" %s (%s)"):format(vers.show_dep(dep), rock_status(dep.name, deps_mode, rocks_provided))) 118 util.printout((" %s (%s)"):format(tostring(dep), rock_status(dep.name, deps_mode, rocks_provided)))
119 end 119 end
120 end 120 end
121end 121end
@@ -172,11 +172,11 @@ function deps.fulfill_dependencies(rockspec, deps_mode)
172 end 172 end
173 173
174 util.printout(("%s %s depends on %s (%s)"):format( 174 util.printout(("%s %s depends on %s (%s)"):format(
175 rockspec.name, rockspec.version, vers.show_dep(dep), rock_status(dep.name, deps_mode, rockspec.rocks_provided))) 175 rockspec.name, rockspec.version, tostring(dep), rock_status(dep.name, deps_mode, rockspec.rocks_provided)))
176 176
177 if dep.constraints[1] and dep.constraints[1].no_upgrade then 177 if dep.constraints[1] and dep.constraints[1].no_upgrade then
178 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")
179 util.printerr(vers.show_dep(dep)..", but is configured to avoid upgrading it") 179 util.printerr(tostring(dep)..", but is configured to avoid upgrading it")
180 util.printerr("automatically. Please upgrade "..dep.name.." with") 180 util.printerr("automatically. Please upgrade "..dep.name.." with")
181 util.printerr(" luarocks install "..dep.name) 181 util.printerr(" luarocks install "..dep.name)
182 util.printerr("or choose an older version of "..rockspec.name.." with") 182 util.printerr("or choose an older version of "..rockspec.name.." with")
@@ -184,12 +184,12 @@ function deps.fulfill_dependencies(rockspec, deps_mode)
184 return nil, "Failed matching dependencies" 184 return nil, "Failed matching dependencies"
185 end 185 end
186 186
187 local url, search_err = search.find_suitable_rock(queries.from_constraints(dep.name, dep.constraints)) 187 local url, search_err = search.find_suitable_rock(dep)
188 if not url then 188 if not url then
189 return nil, "Could not satisfy dependency "..vers.show_dep(dep)..": "..search_err 189 return nil, "Could not satisfy dependency "..tostring(dep)..": "..search_err
190 end 190 end
191 util.printout("Installing "..url) 191 util.printout("Installing "..url)
192 local ok, install_err, errcode = install.command({deps_mode = deps_mode}, url) 192 local ok, install_err, errcode = install.command({deps_mode = deps_mode, namespace = dep.namespace}, url)
193 if not ok then 193 if not ok then
194 return nil, "Failed installing dependency: "..url.." - "..install_err, errcode 194 return nil, "Failed installing dependency: "..url.." - "..install_err, errcode
195 end 195 end
diff --git a/src/luarocks/fetch.lua b/src/luarocks/fetch.lua
index de4a3dee..db99c3d5 100644
--- a/src/luarocks/fetch.lua
+++ b/src/luarocks/fetch.lua
@@ -6,7 +6,8 @@ local fs = require("luarocks.fs")
6local dir = require("luarocks.dir") 6local dir = require("luarocks.dir")
7local type_rockspec = require("luarocks.type.rockspec") 7local type_rockspec = require("luarocks.type.rockspec")
8local path = require("luarocks.path") 8local path = require("luarocks.path")
9local vers = require("luarocks.vers") 9local vers = require("luarocks.core.vers")
10local queries = require("luarocks.queries")
10local persist = require("luarocks.persist") 11local persist = require("luarocks.persist")
11local util = require("luarocks.util") 12local util = require("luarocks.util")
12local cfg = require("luarocks.core.cfg") 13local cfg = require("luarocks.core.cfg")
@@ -210,8 +211,21 @@ function fetch.load_local_rockspec(filename, quick)
210 return nil, filename..": "..err 211 return nil, filename..": "..err
211 end 212 end
212 end 213 end
213 214
214 rockspec.format_is_at_least = vers.format_is_at_least 215 rockspec.format_is_at_least = function(_, v)
216 return parsed_format >= vers.parse_version(v)
217 end
218
219 --- Check if rockspec format version satisfies version requirement.
220 -- @param rockspec table: The rockspec table.
221 -- @param version string: required version.
222 -- @return boolean: true if rockspec format matches version or is newer, false otherwise.
223 do
224 local parsed_format = vers.parse_version(rockspec.rockspec_format or "1.0")
225 rockspec.format_is_at_least = function(self, version)
226 return parsed_format >= vers.parse_version(version)
227 end
228 end
215 229
216 util.platform_overrides(rockspec.build) 230 util.platform_overrides(rockspec.build)
217 util.platform_overrides(rockspec.dependencies) 231 util.platform_overrides(rockspec.dependencies)
@@ -262,7 +276,7 @@ function fetch.load_local_rockspec(filename, quick)
262 276
263 if rockspec.dependencies then 277 if rockspec.dependencies then
264 for i = 1, #rockspec.dependencies do 278 for i = 1, #rockspec.dependencies do
265 local parsed, err = vers.parse_dep(rockspec.dependencies[i]) 279 local parsed, err = queries.from_dep_string(rockspec.dependencies[i])
266 if not parsed then 280 if not parsed then
267 return nil, "Parse error processing dependency '"..rockspec.dependencies[i].."': "..tostring(err) 281 return nil, "Parse error processing dependency '"..rockspec.dependencies[i].."': "..tostring(err)
268 end 282 end
diff --git a/src/luarocks/fetch/git.lua b/src/luarocks/fetch/git.lua
index efd62e6d..a14a5bfb 100644
--- a/src/luarocks/fetch/git.lua
+++ b/src/luarocks/fetch/git.lua
@@ -6,14 +6,14 @@ local unpack = unpack or table.unpack
6 6
7local fs = require("luarocks.fs") 7local fs = require("luarocks.fs")
8local dir = require("luarocks.dir") 8local dir = require("luarocks.dir")
9local vers = require("luarocks.vers") 9local vers = require("luarocks.core.vers")
10local util = require("luarocks.util") 10local util = require("luarocks.util")
11 11
12local cached_git_version 12local cached_git_version
13 13
14--- Get git version. 14--- Get git version.
15-- @param git_cmd string: name of git command. 15-- @param git_cmd string: name of git command.
16-- @return table: git version as returned by luarocks.vers.parse_version. 16-- @return table: git version as returned by luarocks.core.vers.parse_version.
17local function git_version(git_cmd) 17local function git_version(git_cmd)
18 if not cached_git_version then 18 if not cached_git_version then
19 local version_line = io.popen(fs.Q(git_cmd)..' --version'):read() 19 local version_line = io.popen(fs.Q(git_cmd)..' --version'):read()
diff --git a/src/luarocks/manif.lua b/src/luarocks/manif.lua
index df9f22ae..5ac9920d 100644
--- a/src/luarocks/manif.lua
+++ b/src/luarocks/manif.lua
@@ -230,9 +230,12 @@ end
230-- or "all", to use all trees. 230-- or "all", to use all trees.
231-- @return table: An array of strings listing installed 231-- @return table: An array of strings listing installed
232-- versions of a package. 232-- versions of a package.
233function manif.get_versions(name, deps_mode) 233function manif.get_versions(dep, deps_mode)
234 assert(type(name) == "string") 234 assert(type(dep) == "table")
235 assert(type(deps_mode) == "string") 235 assert(type(deps_mode) == "string")
236
237 local name = dep.name
238 local namespace = dep.namespace
236 239
237 local version_set = {} 240 local version_set = {}
238 path.map_trees(deps_mode, function(tree) 241 path.map_trees(deps_mode, function(tree)
@@ -240,7 +243,19 @@ function manif.get_versions(name, deps_mode)
240 243
241 if manifest and manifest.repository[name] then 244 if manifest and manifest.repository[name] then
242 for version in pairs(manifest.repository[name]) do 245 for version in pairs(manifest.repository[name]) do
243 version_set[version] = true 246 if dep.namespace then
247 local ns_file = path.rock_namespace_file(name, version, tree)
248 local fd = io.open(ns_file, "r")
249 if fd then
250 local ns = fd:read("*a")
251 fd:close()
252 if ns == namespace then
253 version_set[version] = true
254 end
255 end
256 else
257 version_set[version] = true
258 end
244 end 259 end
245 end 260 end
246 end) 261 end)
diff --git a/src/luarocks/manif/writer.lua b/src/luarocks/manif/writer.lua
index e6edd27d..a6c70f4d 100644
--- a/src/luarocks/manif/writer.lua
+++ b/src/luarocks/manif/writer.lua
@@ -5,7 +5,7 @@ local cfg = require("luarocks.core.cfg")
5local search = require("luarocks.search") 5local search = require("luarocks.search")
6local repos = require("luarocks.repos") 6local repos = require("luarocks.repos")
7local deps = require("luarocks.deps") 7local deps = require("luarocks.deps")
8local vers = require("luarocks.vers") 8local vers = require("luarocks.core.vers")
9local fs = require("luarocks.fs") 9local fs = require("luarocks.fs")
10local util = require("luarocks.util") 10local util = require("luarocks.util")
11local dir = require("luarocks.dir") 11local dir = require("luarocks.dir")
@@ -277,6 +277,33 @@ function writer.make_rock_manifest(name, version)
277 save_table(install_dir, "rock_manifest", rock_manifest ) 277 save_table(install_dir, "rock_manifest", rock_manifest )
278end 278end
279 279
280-- Writes a 'rock_namespace' file in a locally installed rock directory.
281-- @param name string: the rock name (may be in user/rock format)
282-- @param version string: the rock version
283-- @param namespace string?: the namespace
284-- @return true if successful (or unnecessary, if there is no namespace),
285-- or nil and an error message.
286function writer.make_namespace_file(name, version, namespace)
287 assert(type(name) == "string")
288 assert(type(version) == "string")
289 assert(type(namespace) == "string" or not namespace)
290 name = util.adjust_name_and_namespace(name, { namespace = namespace })
291 name, namespace = util.split_namespace(name)
292 if not namespace then
293 return true
294 end
295 local fd, err = io.open(path.rock_namespace_file(name, version), "w")
296 if not fd then
297 return nil, err
298 end
299 local ok, err = fd:write(namespace)
300 if not ok then
301 return nil, err
302 end
303 fd:close()
304 return true
305end
306
280--- Scan a LuaRocks repository and output a manifest file. 307--- Scan a LuaRocks repository and output a manifest file.
281-- A file called 'manifest' will be written in the root of the given 308-- A file called 'manifest' will be written in the root of the given
282-- repository directory. 309-- repository directory.
diff --git a/src/luarocks/pack.lua b/src/luarocks/pack.lua
index b721a209..a02fb677 100644
--- a/src/luarocks/pack.lua
+++ b/src/luarocks/pack.lua
@@ -4,6 +4,7 @@ local pack = {}
4 4
5local unpack = unpack or table.unpack 5local unpack = unpack or table.unpack
6 6
7local queries = require("luarocks.queries")
7local path = require("luarocks.path") 8local path = require("luarocks.path")
8local repos = require("luarocks.repos") 9local repos = require("luarocks.repos")
9local fetch = require("luarocks.fetch") 10local fetch = require("luarocks.fetch")
@@ -80,8 +81,9 @@ function pack.pack_installed_rock(name, version, tree)
80 assert(type(name) == "string") 81 assert(type(name) == "string")
81 assert(type(version) == "string" or not version) 82 assert(type(version) == "string" or not version)
82 83
84 local query = queries.new(name, version)
83 local repo, repo_url 85 local repo, repo_url
84 name, version, repo, repo_url = search.pick_installed_rock(name, version, tree) 86 name, version, repo, repo_url = search.pick_installed_rock(query, tree)
85 if not name then 87 if not name then
86 return nil, version 88 return nil, version
87 end 89 end
@@ -126,7 +128,7 @@ function pack.pack_installed_rock(name, version, tree)
126 return rock_file 128 return rock_file
127end 129end
128 130
129function pack.pack_binary_rock(name, version, cmd, ...) 131function pack.pack_binary_rock(name, version, cmd)
130 132
131 -- The --pack-binary-rock option for "luarocks build" basically performs 133 -- The --pack-binary-rock option for "luarocks build" basically performs
132 -- "luarocks build" on a temporary tree and then "luarocks pack". The 134 -- "luarocks build" on a temporary tree and then "luarocks pack". The
@@ -142,7 +144,7 @@ function pack.pack_binary_rock(name, version, cmd, ...)
142 util.schedule_function(fs.delete, temp_dir) 144 util.schedule_function(fs.delete, temp_dir)
143 145
144 path.use_tree(temp_dir) 146 path.use_tree(temp_dir)
145 local ok, err = cmd(...) 147 local ok, err = cmd()
146 if not ok then 148 if not ok then
147 return nil, err 149 return nil, err
148 end 150 end
diff --git a/src/luarocks/path.lua b/src/luarocks/path.lua
index 8a56233f..7a569169 100644
--- a/src/luarocks/path.lua
+++ b/src/luarocks/path.lua
@@ -97,6 +97,19 @@ function path.rock_manifest_file(name, version, tree)
97 return dir.path(path.rocks_dir(tree), name, version, "rock_manifest") 97 return dir.path(path.rocks_dir(tree), name, version, "rock_manifest")
98end 98end
99 99
100--- Get the local filename of the rock_namespace file of an installed rock.
101-- @param name string: The package name (without a namespace).
102-- @param version string: The package version.
103-- @param tree string or nil: If given, specifies the local tree to use.
104-- @return string: The resulting path -- does not guarantee that
105-- the package (and by extension, the file) exists.
106function path.rock_namespace_file(name, version, tree)
107 assert(type(name) == "string")
108 assert(type(version) == "string")
109 tree = tree or cfg.root_dir
110 return dir.path(path.rocks_dir(tree), name, version, "rock_namespace")
111end
112
100--- Get the local installation directory for C libraries of a package. 113--- Get the local installation directory for C libraries of a package.
101-- @param name string: The package name. 114-- @param name string: The package name.
102-- @param version string: The package version. 115-- @param version string: The package version.
diff --git a/src/luarocks/queries.lua b/src/luarocks/queries.lua
index 5bd7462e..888d9cf7 100644
--- a/src/luarocks/queries.lua
+++ b/src/luarocks/queries.lua
@@ -1,10 +1,17 @@
1 1
2local queries = {} 2local queries = {}
3 3
4local vers = require("luarocks.vers") 4local vers = require("luarocks.core.vers")
5local util = require("luarocks.util")
5local cfg = require("luarocks.core.cfg") 6local cfg = require("luarocks.core.cfg")
6 7
7local safer = require("safer") 8local query_mt = {}
9
10query_mt.__index = query_mt
11
12function query_mt.type()
13 return "query"
14end
8 15
9--- Convert the arch field of a query table to table format. 16--- Convert the arch field of a query table to table format.
10-- @param input string, table or nil 17-- @param input string, table or nil
@@ -28,24 +35,13 @@ local function arch_to_table(input)
28 end 35 end
29end 36end
30 37
31-- Split name and namespace of a package name.
32-- @param name a name that may be in "namespace/name" format
33-- @return string, string? - name and optionally a namespace
34local function split_namespace(name)
35 local p1, p2 = name:match("^([^/]+)/([^/]+)$")
36 if p1 then
37 return p2, p1
38 end
39 return name
40end
41
42--- Prepare a query in dependency table format. 38--- Prepare a query in dependency table format.
43-- @param name string: The query name. 39-- @param name string: the package name, may contain a namespace.
44-- @param version string or nil: 40-- @param version string?: the package version.
45-- @param substring boolean: match substrings of the name 41-- @param substring boolean?: match substrings of the name
46-- (default is false, match full name) 42-- (default is false, match full name)
47-- @param arch string: a string with pipe-separated accepted arch values 43-- @param arch string?: a string with pipe-separated accepted arch values
48-- @param operator string: operator for version matching (default is "==") 44-- @param operator string?: operator for version matching (default is "==")
49-- @return table: A query in table format 45-- @return table: A query in table format
50function queries.new(name, version, substring, arch, operator) 46function queries.new(name, version, substring, arch, operator)
51 assert(type(name) == "string") 47 assert(type(name) == "string")
@@ -57,9 +53,9 @@ function queries.new(name, version, substring, arch, operator)
57 operator = operator or "==" 53 operator = operator or "=="
58 54
59 local namespace 55 local namespace
60 name, namespace = split_namespace(name) 56 name, namespace = util.split_namespace(name)
61 57
62 local query = { 58 local self = {
63 name = name, 59 name = name,
64 namespace = namespace, 60 namespace = namespace,
65 constraints = {}, 61 constraints = {},
@@ -67,9 +63,9 @@ function queries.new(name, version, substring, arch, operator)
67 arch = arch_to_table(arch), 63 arch = arch_to_table(arch),
68 } 64 }
69 if version then 65 if version then
70 table.insert(query.constraints, { op = operator, version = vers.parse_version(version)}) 66 table.insert(self.constraints, { op = operator, version = vers.parse_version(version)})
71 end 67 end
72 return safer.readonly(query) 68 return setmetatable(self, query_mt)
73end 69end
74 70
75-- Query for all packages 71-- Query for all packages
@@ -80,17 +76,129 @@ function queries.all(arch)
80 return queries.new("", nil, true, arch) 76 return queries.new("", nil, true, arch)
81end 77end
82 78
83function queries.from_constraints(name, constraints) 79do
84 local namespace 80 local parse_constraints
85 name, namespace = split_namespace(name) 81 do
86 local query = { 82 local parse_constraint
87 name = name, 83 do
88 namespace = namespace, 84 local operators = {
89 constraints = constraints, 85 ["=="] = "==",
90 substring = false, 86 ["~="] = "~=",
91 arch = arch_to_table(nil), 87 [">"] = ">",
92 } 88 ["<"] = "<",
93 return safer.readonly(query) 89 [">="] = ">=",
90 ["<="] = "<=",
91 ["~>"] = "~>",
92 -- plus some convenience translations
93 [""] = "==",
94 ["="] = "==",
95 ["!="] = "~="
96 }
97
98 --- Consumes a constraint from a string, converting it to table format.
99 -- For example, a string ">= 1.0, > 2.0" is converted to a table in the
100 -- format {op = ">=", version={1,0}} and the rest, "> 2.0", is returned
101 -- back to the caller.
102 -- @param input string: A list of constraints in string format.
103 -- @return (table, string) or nil: A table representing the same
104 -- constraints and the string with the unused input, or nil if the
105 -- input string is invalid.
106 parse_constraint = function(input)
107 assert(type(input) == "string")
108
109 local no_upgrade, op, version, rest = input:match("^(@?)([<>=~!]*)%s*([%w%.%_%-]+)[%s,]*(.*)")
110 local _op = operators[op]
111 version = vers.parse_version(version)
112 if not _op then
113 return nil, "Encountered bad constraint operator: '"..tostring(op).."' in '"..input.."'"
114 end
115 if not version then
116 return nil, "Could not parse version from constraint: '"..input.."'"
117 end
118 return { op = _op, version = version, no_upgrade = no_upgrade=="@" and true or nil }, rest
119 end
120 end
121
122 --- Convert a list of constraints from string to table format.
123 -- For example, a string ">= 1.0, < 2.0" is converted to a table in the format
124 -- {{op = ">=", version={1,0}}, {op = "<", version={2,0}}}.
125 -- Version tables use a metatable allowing later comparison through
126 -- relational operators.
127 -- @param input string: A list of constraints in string format.
128 -- @return table or nil: A table representing the same constraints,
129 -- or nil if the input string is invalid.
130 parse_constraints = function(input)
131 assert(type(input) == "string")
132
133 local constraints, oinput, constraint = {}, input
134 while #input > 0 do
135 constraint, input = parse_constraint(input)
136 if constraint then
137 table.insert(constraints, constraint)
138 else
139 return nil, "Failed to parse constraint '"..tostring(oinput).."' with error: ".. input
140 end
141 end
142 return constraints
143 end
144 end
145
146 --- Prepare a query in dependency table format.
147 -- @param depstr string: A dependency in string format
148 -- as entered in rockspec files.
149 -- @return table: A query in table format, or nil and an error message in case of errors.
150 function queries.from_dep_string(depstr)
151 assert(type(depstr) == "string")
152
153 local ns_name, rest = depstr:match("^%s*([a-zA-Z0-9%.%-%_]*/?[a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*([^/]*)")
154 if not ns_name then
155 return nil, "failed to extract dependency name from '"..depstr.."'"
156 end
157
158 local constraints, err = parse_constraints(rest)
159 if not constraints then
160 return nil, err
161 end
162
163 local name, namespace = util.split_namespace(ns_name)
164
165 local self = {
166 name = name,
167 namespace = namespace,
168 constraints = constraints,
169 substring = false,
170 arch = arch_to_table(nil),
171 }
172 return setmetatable(self, query_mt)
173 end
174end
175
176--- Build a string representation of a query package name.
177-- Includes namespace, name and version, but not arch or constraints.
178-- @param query table: a query table
179-- @return string: a result such as `my_user/my_rock 1.0` or `my_rock`.
180function queries:__tostring()
181 local out = {}
182 if self.namespace then
183 table.insert(out, self.namespace)
184 table.insert(out, "/")
185 end
186 table.insert(out, self.name)
187
188 if #self.constraints > 0 then
189 local pretty = {}
190 for _, c in ipairs(self.constraints) do
191 if c.op == "==" then
192 table.insert(pretty, tostring(c.version))
193 else
194 table.insert(pretty, c.op .. " " .. tostring(c.version))
195 end
196 end
197 table.insert(out, " ")
198 table.insert(out, table.concat(pretty, ", "))
199 end
200
201 return table.concat(out)
94end 202end
95 203
96return queries 204return queries
diff --git a/src/luarocks/remove.lua b/src/luarocks/remove.lua
index a469d149..1b4e3562 100644
--- a/src/luarocks/remove.lua
+++ b/src/luarocks/remove.lua
@@ -24,7 +24,7 @@ local function check_dependents(name, versions, deps_mode)
24 end 24 end
25 local local_rocks = {} 25 local local_rocks = {}
26 local query_all = queries.all() 26 local query_all = queries.all()
27 search.manifest_search(local_rocks, cfg.rocks_dir, query_all) 27 search.local_manifest_search(local_rocks, cfg.rocks_dir, query_all)
28 local_rocks[name] = nil 28 local_rocks[name] = nil
29 for rock_name, rock_versions in pairs(local_rocks) do 29 for rock_name, rock_versions in pairs(local_rocks) do
30 for rock_version, _ in pairs(rock_versions) do 30 for rock_version, _ in pairs(rock_versions) do
@@ -106,7 +106,7 @@ end
106function remove.remove_other_versions(name, version, force, fast) 106function remove.remove_other_versions(name, version, force, fast)
107 local results = {} 107 local results = {}
108 local query = queries.new(name, version, false, nil, "~=") 108 local query = queries.new(name, version, false, nil, "~=")
109 search.manifest_search(results, cfg.rocks_dir, query) 109 search.local_manifest_search(results, cfg.rocks_dir, query)
110 if results[name] then 110 if results[name] then
111 return remove.remove_search_results(results, name, cfg.deps_mode, force, fast) 111 return remove.remove_search_results(results, name, cfg.deps_mode, force, fast)
112 end 112 end
diff --git a/src/luarocks/repos.lua b/src/luarocks/repos.lua
index 12927153..35f5e3bc 100644
--- a/src/luarocks/repos.lua
+++ b/src/luarocks/repos.lua
@@ -8,7 +8,7 @@ local cfg = require("luarocks.core.cfg")
8local util = require("luarocks.util") 8local util = require("luarocks.util")
9local dir = require("luarocks.dir") 9local dir = require("luarocks.dir")
10local manif = require("luarocks.manif") 10local manif = require("luarocks.manif")
11local vers = require("luarocks.vers") 11local vers = require("luarocks.core.vers")
12 12
13-- Tree of files installed by a package are stored 13-- Tree of files installed by a package are stored
14-- in its rock manifest. Some of these files have to 14-- in its rock manifest. Some of these files have to
diff --git a/src/luarocks/results.lua b/src/luarocks/results.lua
new file mode 100644
index 00000000..3e743883
--- /dev/null
+++ b/src/luarocks/results.lua
@@ -0,0 +1,62 @@
1local results = {}
2
3local vers = require("luarocks.core.vers")
4local util = require("luarocks.util")
5
6local result_mt = {}
7
8result_mt.__index = result_mt
9
10function result_mt.type()
11 return "result"
12end
13
14function results.new(name, version, repo, arch, namespace)
15 assert(type(name) == "string")
16 assert(type(version) == "string")
17 assert(type(repo) == "string")
18 assert(type(arch) == "string" or not arch)
19 assert(type(namespace) == "string" or not namespace)
20
21 if not namespace then
22 name, namespace = util.split_namespace(name)
23 end
24
25 local self = {
26 name = name,
27 version = version,
28 namespace = namespace,
29 arch = arch,
30 repo = repo,
31 }
32
33 return setmetatable(self, result_mt)
34end
35
36--- Test the name field of a query.
37-- If query has a boolean field substring set to true,
38-- then substring match is performed; otherwise, exact string
39-- comparison is done.
40-- @param query table: A query in dependency table format.
41-- @param name string: A package name.
42-- @return boolean: True if names match, false otherwise.
43local function match_name(query, name)
44 if query.substring then
45 return name:find(query.name, 0, true) and true or false
46 else
47 return name == query.name
48 end
49end
50
51--- Returns true if the result satisfies a given query.
52-- @param query: a query.
53-- @return boolean.
54function result_mt:satisfies(query)
55 assert(query:type() == "query")
56 return match_name(query, self.name)
57 and (query.arch[self.arch] or query.arch["any"])
58 and ((not query.namespace) or (query.namespace == self.namespace))
59 and vers.match_constraints(vers.parse_version(self.version), query.constraints)
60end
61
62return results
diff --git a/src/luarocks/search.lua b/src/luarocks/search.lua
index 4e0cb847..54ddd517 100644
--- a/src/luarocks/search.lua
+++ b/src/luarocks/search.lua
@@ -3,103 +3,68 @@ local search = {}
3local dir = require("luarocks.dir") 3local dir = require("luarocks.dir")
4local path = require("luarocks.path") 4local path = require("luarocks.path")
5local manif = require("luarocks.manif") 5local manif = require("luarocks.manif")
6local vers = require("luarocks.vers") 6local vers = require("luarocks.core.vers")
7local cfg = require("luarocks.core.cfg") 7local cfg = require("luarocks.core.cfg")
8local util = require("luarocks.util") 8local util = require("luarocks.util")
9local queries = require("luarocks.queries") 9local queries = require("luarocks.queries")
10local results = require("luarocks.results")
10 11
11--- Store a search result (a rock or rockspec) in the results table. 12--- Store a search result (a rock or rockspec) in the result tree.
12-- @param results table: The results table, where keys are package names and 13-- @param result_tree table: The result tree, where keys are package names and
13-- values are tables matching version strings to arrays of 14-- values are tables matching version strings to arrays of
14-- tables with fields "arch" and "repo". 15-- tables with fields "arch" and "repo".
15-- @param name string: Package name. 16-- @param result table: A result.
16-- @param version string: Package version. 17function search.store_result(result_tree, result)
17-- @param arch string: Architecture of rock ("all", "src" or platform 18 assert(type(result_tree) == "table")
18-- identifier), "rockspec" or "installed" 19 assert(result:type() == "result")
19-- @param repo string: Pathname of a local repository of URL of
20-- rocks server.
21function search.store_result(results, name, version, arch, repo)
22 assert(type(results) == "table")
23 assert(type(name) == "string")
24 assert(type(version) == "string")
25 assert(type(arch) == "string")
26 assert(type(repo) == "string")
27
28 if not results[name] then results[name] = {} end
29 if not results[name][version] then results[name][version] = {} end
30 table.insert(results[name][version], {
31 arch = arch,
32 repo = repo
33 })
34end
35 20
36--- Test the name field of a query. 21 local name = result.name
37-- If query has a boolean field substring set to true, 22 local version = result.version
38-- then substring match is performed; otherwise, exact string 23
39-- comparison is done. 24 if not result_tree[name] then result_tree[name] = {} end
40-- @param query table: A query in dependency table format. 25 if not result_tree[name][version] then result_tree[name][version] = {} end
41-- @param name string: A package name. 26 table.insert(result_tree[name][version], {
42-- @return boolean: True if names match, false otherwise. 27 arch = result.arch,
43local function match_name(query, name) 28 repo = result.repo
44 assert(type(query) == "table") 29 })
45 assert(type(name) == "string")
46 if query.substring then
47 return name:find(query.name, 0, true) and true or false
48 else
49 return name == query.name
50 end
51end 30end
52 31
53--- Store a match in a results table if version matches query. 32--- Store a match in a result tree if version matches query.
54-- Name, version, arch and repository path are stored in a given 33-- Name, version, arch and repository path are stored in a given
55-- table, optionally checking if version and arch (if given) match 34-- table, optionally checking if version and arch (if given) match
56-- a query. 35-- a query.
57-- @param results table: The results table, where keys are package names and 36-- @param result_tree table: The result tree, where keys are package names and
58-- values are tables matching version strings to arrays of 37-- values are tables matching version strings to arrays of
59-- tables with fields "arch" and "repo". 38-- tables with fields "arch" and "repo".
60-- @param repo string: URL or pathname of the repository. 39-- @param result table: a result object.
61-- @param name string: The name of the package being tested. 40-- @param query table: a query object.
62-- @param version string: The version of the package being tested. 41local function store_if_match(result_tree, result, query)
63-- @param arch string: The arch of the package being tested. 42 assert(result:type() == "result")
64-- @param query table: A table describing the query in dependency 43 assert(query:type() == "query")
65-- format (for example, {name = "filesystem", substring = true, 44
66-- constraints = {op = "~>", version = {1,0}}}, arch = "rockspec"). 45 if result:satisfies(query) then
67-- If the arch field is omitted, the local architecture (cfg.arch) 46 search.store_result(result_tree, result)
68-- is used. The special value "any" is also recognized, returning all
69-- matches regardless of architecture.
70local function store_if_match(results, repo, name, version, arch, query)
71 if match_name(query, name) then
72 if query.arch[arch] or query.arch["any"] then
73 if vers.match_constraints(vers.parse_version(version), query.constraints) then
74 search.store_result(results, name, version, arch, repo)
75 end
76 end
77 end 47 end
78end 48end
79 49
80--- Perform search on a local repository. 50--- Perform search on a local repository.
81-- @param repo string: The pathname of the local repository. 51-- @param repo string: The pathname of the local repository.
82-- @param query table: A table describing the query in dependency 52-- @param query table: a query object.
83-- format (for example, {name = "filesystem", substring = true, 53-- @param result_tree table or nil: If given, this table will store the
84-- constraints = {op = "~>", version = {1,0}}}, arch = "rockspec"). 54-- result tree; if not given, a new table will be created.
85-- If the arch field is omitted, the local architecture (cfg.arch) 55-- @return table: The result tree, where keys are package names and
86-- is used. The special value "any" is also recognized, returning all
87-- matches regardless of architecture.
88-- @param results table or nil: If given, this table will store the
89-- results; if not given, a new table will be created.
90-- @return table: The results table, where keys are package names and
91-- values are tables matching version strings to arrays of 56-- values are tables matching version strings to arrays of
92-- tables with fields "arch" and "repo". 57-- tables with fields "arch" and "repo".
93-- If a table was given in the "results" parameter, that is the result value. 58-- If a table was given in the "result_tree" parameter, that is the result value.
94function search.disk_search(repo, query, results) 59function search.disk_search(repo, query, result_tree)
95 assert(type(repo) == "string") 60 assert(type(repo) == "string")
96 assert(type(query) == "table") 61 assert(query:type() == "query")
97 assert(type(results) == "table" or not results) 62 assert(type(result_tree) == "table" or not result_tree)
98 63
99 local fs = require("luarocks.fs") 64 local fs = require("luarocks.fs")
100 65
101 if not results then 66 if not result_tree then
102 results = {} 67 result_tree = {}
103 end 68 end
104 69
105 for name in fs.dir(repo) do 70 for name in fs.dir(repo) do
@@ -107,38 +72,49 @@ function search.disk_search(repo, query, results)
107 local rname, rversion, rarch = path.parse_name(name) 72 local rname, rversion, rarch = path.parse_name(name)
108 73
109 if rname and (pathname:match(".rockspec$") or pathname:match(".rock$")) then 74 if rname and (pathname:match(".rockspec$") or pathname:match(".rock$")) then
110 store_if_match(results, repo, rname, rversion, rarch, query) 75 local result = results.new(rname, rversion, repo, rarch)
76 store_if_match(result_tree, result, query)
111 elseif fs.is_dir(pathname) then 77 elseif fs.is_dir(pathname) then
112 for version in fs.dir(pathname) do 78 for version in fs.dir(pathname) do
113 if version:match("-%d+$") then 79 if version:match("-%d+$") then
114 store_if_match(results, repo, name, version, "installed", query) 80 local namespace = nil
81 -- FIXME read rock_namespace file
82 local result = results.new(name, version, repo, "installed", namespace)
83 store_if_match(result_tree, result, query)
115 end 84 end
116 end 85 end
117 end 86 end
118 end 87 end
119 return results 88 return result_tree
89end
90
91local function read_namespace(name, version, tree)
92 local namespace
93 local fd = io.open(path.rock_namespace_file(name, version, tree), "r")
94 if fd then
95 namespace = fd:read("*a")
96 fd:close()
97 end
98 return namespace
120end 99end
121 100
122--- Perform search on a rocks server or tree. 101--- Perform search on a rocks server or tree.
123-- @param results table: The results table, where keys are package names and 102-- @param result_tree table: The result tree, where keys are package names and
124-- values are tables matching version strings to arrays of 103-- values are tables matching version strings to arrays of
125-- tables with fields "arch" and "repo". 104-- tables with fields "arch" and "repo".
126-- @param repo string: The URL of a rocks server or 105-- @param repo string: The URL of a rocks server or
127-- the pathname of a rocks tree (as returned by path.rocks_dir()). 106-- the pathname of a rocks tree (as returned by path.rocks_dir()).
128-- @param query table: A table describing the query in dependency 107-- @param query table: a query object.
129-- format (for example, {name = "filesystem", substring = true,
130-- constraints = {op = "~>", version = {1,0}}}, arch = "rockspec").
131-- If the arch field is omitted, the local architecture (cfg.arch)
132-- is used. The special value "any" is also recognized, returning all
133-- matches regardless of architecture.
134-- @param lua_version string: Lua version in "5.x" format, defaults to installed version. 108-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
109-- @param is_local boolean
135-- @return true or, in case of errors, nil, an error message and an optional error code. 110-- @return true or, in case of errors, nil, an error message and an optional error code.
136function search.manifest_search(results, repo, query, lua_version) 111local function manifest_search(result_tree, repo, query, lua_version, is_local)
137 assert(type(results) == "table") 112 assert(type(result_tree) == "table")
138 assert(type(repo) == "string") 113 assert(type(repo) == "string")
139 assert(type(query) == "table") 114 assert(query:type() == "query")
140 115
141 if query.namespace then 116 -- FIXME do not add this in local repos
117 if (not is_local) and query.namespace then
142 repo = repo .. "/manifests/" .. query.namespace 118 repo = repo .. "/manifests/" .. query.namespace
143 end 119 end
144 120
@@ -148,24 +124,34 @@ function search.manifest_search(results, repo, query, lua_version)
148 end 124 end
149 for name, versions in pairs(manifest.repository) do 125 for name, versions in pairs(manifest.repository) do
150 for version, items in pairs(versions) do 126 for version, items in pairs(versions) do
127 local namespace = is_local and read_namespace(name, version, repo) or query.namespace
151 for _, item in ipairs(items) do 128 for _, item in ipairs(items) do
152 store_if_match(results, repo, name, version, item.arch, query) 129 local result = results.new(name, version, repo, item.arch, namespace)
130 store_if_match(result_tree, result, query)
153 end 131 end
154 end 132 end
155 end 133 end
156 return true 134 return true
157end 135end
158 136
137local function remote_manifest_search(result_tree, repo, query, lua_version)
138 return manifest_search(result_tree, repo, query, lua_version, false)
139end
140
141function search.local_manifest_search(result_tree, repo, query, lua_version)
142 return manifest_search(result_tree, repo, query, lua_version, true)
143end
144
159--- Search on all configured rocks servers. 145--- Search on all configured rocks servers.
160-- @param query table: A dependency query. 146-- @param query table: a query object.
161-- @param lua_version string: Lua version in "5.x" format, defaults to installed version. 147-- @param lua_version string: Lua version in "5.x" format, defaults to installed version.
162-- @return table: A table where keys are package names 148-- @return table: A table where keys are package names
163-- and values are tables matching version strings to arrays of 149-- and values are tables matching version strings to arrays of
164-- tables with fields "arch" and "repo". 150-- tables with fields "arch" and "repo".
165function search.search_repos(query, lua_version) 151function search.search_repos(query, lua_version)
166 assert(type(query) == "table") 152 assert(query:type() == "query")
167 153
168 local results = {} 154 local result_tree = {}
169 for _, repo in ipairs(cfg.rocks_servers) do 155 for _, repo in ipairs(cfg.rocks_servers) do
170 if not cfg.disabled_servers[repo] then 156 if not cfg.disabled_servers[repo] then
171 if type(repo) == "string" then 157 if type(repo) == "string" then
@@ -176,7 +162,7 @@ function search.search_repos(query, lua_version)
176 if protocol == "file" then 162 if protocol == "file" then
177 mirror = pathname 163 mirror = pathname
178 end 164 end
179 local ok, err, errcode = search.manifest_search(results, mirror, query, lua_version) 165 local ok, err, errcode = remote_manifest_search(result_tree, mirror, query, lua_version)
180 if errcode == "network" then 166 if errcode == "network" then
181 cfg.disabled_servers[repo] = true 167 cfg.disabled_servers[repo] = true
182 end 168 end
@@ -190,16 +176,17 @@ function search.search_repos(query, lua_version)
190 end 176 end
191 -- search through rocks in cfg.rocks_provided 177 -- search through rocks in cfg.rocks_provided
192 local provided_repo = "provided by VM or rocks_provided" 178 local provided_repo = "provided by VM or rocks_provided"
193 for name, versions in pairs(cfg.rocks_provided) do 179 for name, version in pairs(cfg.rocks_provided) do
194 store_if_match(results, provided_repo, name, versions, "installed", query) 180 local result = results.new(name, version, provided_repo, "installed")
181 store_if_match(result_tree, result, query)
195 end 182 end
196 return results 183 return result_tree
197end 184end
198 185
199--- Get the URL for the latest in a set of versions. 186--- Get the URL for the latest in a set of versions.
200-- @param name string: The package name to be used in the URL. 187-- @param name string: The package name to be used in the URL.
201-- @param versions table: An array of version informations, as stored 188-- @param versions table: An array of version informations, as stored
202-- in search results tables. 189-- in search result trees.
203-- @return string or nil: the URL for the latest version if one could 190-- @return string or nil: the URL for the latest version if one could
204-- be picked, or nil. 191-- be picked, or nil.
205local function pick_latest_version(name, versions) 192local function pick_latest_version(name, versions)
@@ -227,31 +214,32 @@ local function pick_latest_version(name, versions)
227end 214end
228 215
229-- Find out which other Lua versions provide rock versions matching a query, 216-- Find out which other Lua versions provide rock versions matching a query,
230-- @param query table: A dependency query matching a single rock. 217-- @param query table: a query object.
231-- @return table: array of Lua versions supported, in "5.x" format. 218-- @return table: array of Lua versions supported, in "5.x" format.
232local function supported_lua_versions(query) 219local function supported_lua_versions(query)
233 local results = {} 220 assert(query:type() == "query")
221 local result_tree = {}
234 222
235 for lua_version in util.lua_versions() do 223 for lua_version in util.lua_versions() do
236 if lua_version ~= cfg.lua_version then 224 if lua_version ~= cfg.lua_version then
237 if search.search_repos(query, lua_version)[query.name] then 225 if search.search_repos(query, lua_version)[query.name] then
238 table.insert(results, lua_version) 226 table.insert(result_tree, lua_version)
239 end 227 end
240 end 228 end
241 end 229 end
242 230
243 return results 231 return result_tree
244end 232end
245 233
246--- Attempt to get a single URL for a given search for a rock. 234--- Attempt to get a single URL for a given search for a rock.
247-- @param query table: A dependency query matching a single rock. 235-- @param query table: a query object.
248-- @return string or (nil, string): URL for latest matching version 236-- @return string or (nil, string): URL for latest matching version
249-- of the rock if it was found, or nil followed by an error message. 237-- of the rock if it was found, or nil followed by an error message.
250function search.find_suitable_rock(query) 238function search.find_suitable_rock(query)
251 assert(type(query) == "table") 239 assert(query:type() == "query")
252 240
253 local results = search.search_repos(query) 241 local result_tree = search.search_repos(query)
254 local first_rock = next(results) 242 local first_rock = next(result_tree)
255 if not first_rock then 243 if not first_rock then
256 if cfg.rocks_provided[query.name] == nil then 244 if cfg.rocks_provided[query.name] == nil then
257 -- Check if constraints are satisfiable with other Lua versions. 245 -- Check if constraints are satisfiable with other Lua versions.
@@ -277,7 +265,7 @@ function search.find_suitable_rock(query)
277 end 265 end
278 266
279 return nil, "No results matching query were found." 267 return nil, "No results matching query were found."
280 elseif next(results, first_rock) then 268 elseif next(result_tree, first_rock) then
281 -- Shouldn't happen as query must match only one package. 269 -- Shouldn't happen as query must match only one package.
282 return nil, "Several rocks matched query." 270 return nil, "Several rocks matched query."
283 elseif cfg.rocks_provided[query.name] ~= nil then 271 elseif cfg.rocks_provided[query.name] ~= nil then
@@ -285,19 +273,18 @@ function search.find_suitable_rock(query)
285 return nil, "Rock "..query.name.." "..cfg.rocks_provided[query.name].. 273 return nil, "Rock "..query.name.." "..cfg.rocks_provided[query.name]..
286 " was found but it is provided by VM or 'rocks_provided' in the config file." 274 " was found but it is provided by VM or 'rocks_provided' in the config file."
287 else 275 else
288 return pick_latest_version(query.name, results[first_rock]) 276 return pick_latest_version(query.name, result_tree[first_rock])
289 end 277 end
290end 278end
291 279
292--- Print a list of rocks/rockspecs on standard output. 280--- Print a list of rocks/rockspecs on standard output.
293-- @param results table: A table where keys are package names and versions 281-- @param result_tree table: A result tree.
294-- are tables matching version strings to an array of rocks servers.
295-- @param porcelain boolean or nil: A flag to force machine-friendly output. 282-- @param porcelain boolean or nil: A flag to force machine-friendly output.
296function search.print_results(results, porcelain) 283function search.print_result_tree(result_tree, porcelain)
297 assert(type(results) == "table") 284 assert(type(result_tree) == "table")
298 assert(type(porcelain) == "boolean" or not porcelain) 285 assert(type(porcelain) == "boolean" or not porcelain)
299 286
300 for package, versions in util.sortedpairs(results) do 287 for package, versions in util.sortedpairs(result_tree) do
301 if not porcelain then 288 if not porcelain then
302 util.printout(package) 289 util.printout(package)
303 end 290 end
@@ -331,17 +318,17 @@ function search.act_on_src_or_rockspec(action, name, version, ...)
331 assert(type(name) == "string") 318 assert(type(name) == "string")
332 assert(type(version) == "string" or not version) 319 assert(type(version) == "string" or not version)
333 320
334 local query = queries.new(name, version, nil, "src|rockspec") 321 local _, namespace = util.split_namespace(name)
322 local query = queries.new(name, version, false, "src|rockspec")
335 local url, err = search.find_suitable_rock(query) 323 local url, err = search.find_suitable_rock(query)
336 if not url then 324 if not url then
337 return nil, "Could not find a result named "..name..(version and " "..version or "")..": "..err 325 return nil, "Could not find a result named "..name..(version and " "..version or "")..": "..err
338 end 326 end
339 return action(url, ...) 327 return action(url, namespace, ...)
340end 328end
341 329
342function search.pick_installed_rock(name, version, given_tree) 330function search.pick_installed_rock(query, given_tree)
343 local results = {} 331 local result_tree = {}
344 local query = queries.new(name, version, true)
345 local tree_map = {} 332 local tree_map = {}
346 local trees = cfg.rocks_trees 333 local trees = cfg.rocks_trees
347 if given_tree then 334 if given_tree then
@@ -350,16 +337,15 @@ function search.pick_installed_rock(name, version, given_tree)
350 for _, tree in ipairs(trees) do 337 for _, tree in ipairs(trees) do
351 local rocks_dir = path.rocks_dir(tree) 338 local rocks_dir = path.rocks_dir(tree)
352 tree_map[rocks_dir] = tree 339 tree_map[rocks_dir] = tree
353 search.manifest_search(results, rocks_dir, query) 340 search.local_manifest_search(result_tree, rocks_dir, query)
354 end 341 end
355 342 if not next(result_tree) then
356 if not next(results) then -- 343 return nil, "cannot find package "..tostring(query).."\nUse 'list' to find installed rocks."
357 return nil,"cannot find package "..name.." "..(version or "").."\nUse 'list' to find installed rocks."
358 end 344 end
359 345
360 version = nil 346 local version = nil
361 local repo_url 347 local repo_url
362 local package, versions = util.sortedpairs(results)() 348 local package, versions = util.sortedpairs(result_tree)()
363 --question: what do we do about multiple versions? This should 349 --question: what do we do about multiple versions? This should
364 --give us the latest version on the last repo (which is usually the global one) 350 --give us the latest version on the last repo (which is usually the global one)
365 for vs, repositories in util.sortedpairs(versions, vers.compare_versions) do 351 for vs, repositories in util.sortedpairs(versions, vers.compare_versions) do
@@ -368,7 +354,7 @@ function search.pick_installed_rock(name, version, given_tree)
368 end 354 end
369 355
370 local repo = tree_map[repo_url] 356 local repo = tree_map[repo_url]
371 return name, version, repo, repo_url 357 return query.name, version, repo, repo_url
372end 358end
373 359
374return search 360return search
diff --git a/src/luarocks/type/rockspec.lua b/src/luarocks/type/rockspec.lua
index 5ff48177..214f8e0f 100644
--- a/src/luarocks/type/rockspec.lua
+++ b/src/luarocks/type/rockspec.lua
@@ -39,7 +39,14 @@ local rockspec_types = {
39 }, 39 },
40 dependencies = { 40 dependencies = {
41 platforms = {}, -- recursively defined below 41 platforms = {}, -- recursively defined below
42 _any = string_1, 42 _any = {
43 _type = "string",
44 _name = "a valid dependency string",
45 _patterns = {
46 ["1.0"] = "%s*([a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*([^/]*)",
47 ["3.0"] = "%s*([a-zA-Z0-9%.%-%_]*/?[a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*([^/]*)",
48 },
49 },
43 }, 50 },
44 supported_platforms = { 51 supported_platforms = {
45 _any = string_1, 52 _any = string_1,
@@ -123,8 +130,13 @@ function type_rockspec.check(rockspec, globals)
123 rockspec.rockspec_format = "1.0" 130 rockspec.rockspec_format = "1.0"
124 end 131 end
125 local ok, err = type_check.check_undeclared_globals(globals, rockspec_types) 132 local ok, err = type_check.check_undeclared_globals(globals, rockspec_types)
126 if not ok then return nil, err end 133 if ok then
127 return type_check.type_check_table(rockspec.rockspec_format, rockspec, rockspec_types, "") 134 ok, err = type_check.type_check_table(rockspec.rockspec_format, rockspec, rockspec_types, "")
135 end
136 if ok then
137 return true
138 end
139 return nil, err .. " (rockspec format " .. rockspec.rockspec_format .. ")"
128end 140end
129 141
130return type_rockspec 142return type_rockspec
diff --git a/src/luarocks/type_check.lua b/src/luarocks/type_check.lua
index 250c6258..9e3b7c9e 100644
--- a/src/luarocks/type_check.lua
+++ b/src/luarocks/type_check.lua
@@ -55,9 +55,11 @@ local function type_check_item(version, item, typetbl, context)
55 if item_type ~= "string" then 55 if item_type ~= "string" then
56 return nil, "Type mismatch on field "..context..": expected a string, got "..item_type 56 return nil, "Type mismatch on field "..context..": expected a string, got "..item_type
57 end 57 end
58 if typetbl._pattern then 58 local pattern = (typetbl._patterns and typetbl._patterns[version]) or typetbl._pattern
59 if not item:match("^"..typetbl._pattern.."$") then 59 if pattern then
60 return nil, "Type mismatch on field "..context..": invalid value "..item.." does not match '"..typetbl._pattern.."'" 60 if not item:match("^"..pattern.."$") then
61 local what = typetbl._name or ("'"..pattern.."'")
62 return nil, "Type mismatch on field "..context..": invalid value '"..item.."' does not match " .. what
61 end 63 end
62 end 64 end
63 elseif expected_type == "table" then 65 elseif expected_type == "table" then
diff --git a/src/luarocks/util.lua b/src/luarocks/util.lua
index bc8fc049..76b46d55 100644
--- a/src/luarocks/util.lua
+++ b/src/luarocks/util.lua
@@ -14,6 +14,7 @@ util.split_string = core.split_string
14util.keys = core.keys 14util.keys = core.keys
15util.printerr = core.printerr 15util.printerr = core.printerr
16util.sortedpairs = core.sortedpairs 16util.sortedpairs = core.sortedpairs
17util.warning = core.warning
17 18
18local unpack = unpack or table.unpack 19local unpack = unpack or table.unpack
19 20
@@ -113,6 +114,7 @@ local supported_flags = {
113 ["lua-libdir"] = true, 114 ["lua-libdir"] = true,
114 ["modules"] = true, 115 ["modules"] = true,
115 ["mversion"] = true, 116 ["mversion"] = true,
117 ["namespace"] = "<namespace>",
116 ["no-refresh"] = true, 118 ["no-refresh"] = true,
117 ["nodeps"] = true, 119 ["nodeps"] = true,
118 ["old-versions"] = true, 120 ["old-versions"] = true,
@@ -323,12 +325,6 @@ function util.printout(...)
323 io.stdout:write("\n") 325 io.stdout:write("\n")
324end 326end
325 327
326--- Display a warning message.
327-- @param msg string: the warning message
328function util.warning(msg)
329 util.printerr("Warning: "..msg)
330end
331
332function util.title(msg, porcelain, underline) 328function util.title(msg, porcelain, underline)
333 if porcelain then return end 329 if porcelain then return end
334 util.printout() 330 util.printout()
@@ -397,7 +393,7 @@ local function collect_rockspecs(versions, paths, unnamed_paths, subdir)
397 local fs = require("luarocks.fs") 393 local fs = require("luarocks.fs")
398 local dir = require("luarocks.dir") 394 local dir = require("luarocks.dir")
399 local path = require("luarocks.path") 395 local path = require("luarocks.path")
400 local vers = require("luarocks.vers") 396 local vers = require("luarocks.core.vers")
401 397
402 if fs.is_dir(subdir) then 398 if fs.is_dir(subdir) then
403 for file in fs.dir(subdir) do 399 for file in fs.dir(subdir) do
@@ -459,4 +455,40 @@ function util.LQ(s)
459 return ("%q"):format(s) 455 return ("%q"):format(s)
460end 456end
461 457
458--- Normalize the --namespace flag and the user/rock syntax for namespaces.
459-- If a namespace is given in user/rock syntax, update the --namespace flag;
460-- If a namespace is given in --namespace flag, update the user/rock syntax.
461-- In case of conflicts, the user/rock syntax takes precedence.
462function util.adjust_name_and_namespace(name, flags)
463 assert(type(name) == "string" or not name)
464 assert(type(flags) == "table")
465
466 if not name then
467 return
468 elseif name:match("%.rockspec$") or name:match("%.rock$") then
469 return name
470 end
471
472 local namespace
473 name, namespace = util.split_namespace(name)
474 if namespace then
475 flags["namespace"] = namespace
476 end
477 if flags["namespace"] then
478 name = flags["namespace"] .. "/" .. name
479 end
480 return name:lower()
481end
482
483-- Split name and namespace of a package name.
484-- @param name a name that may be in "namespace/name" format
485-- @return string, string? - name and optionally a namespace
486function util.split_namespace(name)
487 local p1, p2 = name:match("^([^/]+)/([^/]+)$")
488 if p1 then
489 return p2, p1
490 end
491 return name
492end
493
462return util 494return util
diff --git a/src/luarocks/vers.lua b/src/luarocks/vers.lua
deleted file mode 100644
index c1dfbd39..00000000
--- a/src/luarocks/vers.lua
+++ /dev/null
@@ -1,126 +0,0 @@
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.
12local vers = {}
13
14local core = require("luarocks.core.vers")
15
16vers.parse_version = core.parse_version
17vers.compare_versions = core.compare_versions
18vers.match_constraints = core.match_constraints
19
20--- Check if rockspec format version satisfies version requirement.
21-- @param rockspec table: The rockspec table.
22-- @param version string: required version.
23-- @return boolean: true if rockspec format matches version or is newer, false otherwise.
24function vers.format_is_at_least(rockspec, version)
25 local rockspec_format = rockspec.rockspec_format or "1.0"
26 return vers.parse_version(rockspec_format) >= vers.parse_version(version)
27end
28
29local operators = {
30 ["=="] = "==",
31 ["~="] = "~=",
32 [">"] = ">",
33 ["<"] = "<",
34 [">="] = ">=",
35 ["<="] = "<=",
36 ["~>"] = "~>",
37 -- plus some convenience translations
38 [""] = "==",
39 ["="] = "==",
40 ["!="] = "~="
41}
42
43--- Consumes a constraint from a string, converting it to table format.
44-- For example, a string ">= 1.0, > 2.0" is converted to a table in the
45-- format {op = ">=", version={1,0}} and the rest, "> 2.0", is returned
46-- back to the caller.
47-- @param input string: A list of constraints in string format.
48-- @return (table, string) or nil: A table representing the same
49-- constraints and the string with the unused input, or nil if the
50-- input string is invalid.
51local function parse_constraint(input)
52 assert(type(input) == "string")
53
54 local no_upgrade, op, version, rest = input:match("^(@?)([<>=~!]*)%s*([%w%.%_%-]+)[%s,]*(.*)")
55 local _op = operators[op]
56 version = vers.parse_version(version)
57 if not _op then
58 return nil, "Encountered bad constraint operator: '"..tostring(op).."' in '"..input.."'"
59 end
60 if not version then
61 return nil, "Could not parse version from constraint: '"..input.."'"
62 end
63 return { op = _op, version = version, no_upgrade = no_upgrade=="@" and true or nil }, rest
64end
65
66--- Convert a list of constraints from string to table format.
67-- For example, a string ">= 1.0, < 2.0" is converted to a table in the format
68-- {{op = ">=", version={1,0}}, {op = "<", version={2,0}}}.
69-- Version tables use a metatable allowing later comparison through
70-- relational operators.
71-- @param input string: A list of constraints in string format.
72-- @return table or nil: A table representing the same constraints,
73-- or nil if the input string is invalid.
74function vers.parse_constraints(input)
75 assert(type(input) == "string")
76
77 local constraints, oinput, constraint = {}, input
78 while #input > 0 do
79 constraint, input = parse_constraint(input)
80 if constraint then
81 table.insert(constraints, constraint)
82 else
83 return nil, "Failed to parse constraint '"..tostring(oinput).."' with error: ".. input
84 end
85 end
86 return constraints
87end
88
89--- Convert a dependency from string to table format.
90-- For example, a string "foo >= 1.0, < 2.0"
91-- is converted to a table in the format
92-- {name = "foo", constraints = {{op = ">=", version={1,0}},
93-- {op = "<", version={2,0}}}}. Version tables use a metatable
94-- allowing later comparison through relational operators.
95-- @param dep string: A dependency in string format
96-- as entered in rockspec files.
97-- @return table or nil: A table representing the same dependency relation,
98-- or nil if the input string is invalid.
99function vers.parse_dep(dep)
100 assert(type(dep) == "string")
101
102 local name, rest = dep:match("^%s*([a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*(.*)")
103 if not name then return nil, "failed to extract dependency name from '"..tostring(dep).."'" end
104 local constraints, err = vers.parse_constraints(rest)
105 if not constraints then return nil, err end
106 return { name = name, constraints = constraints }
107end
108
109--- Convert a dependency in table format to a string.
110-- @param dep table: The dependency in table format
111-- @return string: The dependency information pretty-printed as a string.
112function vers.show_dep(dep)
113 assert(type(dep) == "table")
114
115 if #dep.constraints > 0 then
116 local pretty = {}
117 for _, c in ipairs(dep.constraints) do
118 table.insert(pretty, c.op .. " " .. tostring(c.version))
119 end
120 return dep.name.." "..table.concat(pretty, ", ")
121 else
122 return dep.name
123 end
124end
125
126return vers