diff options
author | Hisham Muhammad <hisham@gobolinux.org> | 2019-11-08 18:19:17 -0300 |
---|---|---|
committer | Hisham Muhammad <hisham@gobolinux.org> | 2019-11-29 18:36:42 -0300 |
commit | acf8bcb82ae697a5bac94bfbe93c3ad9d7487795 (patch) | |
tree | 62b7239b8701526d69833d9a64f5757bdee2e1df | |
parent | dfc277954d2fe2586dc491cdc1216bae22399251 (diff) | |
download | luarocks-acf8bcb82ae697a5bac94bfbe93c3ad9d7487795.tar.gz luarocks-acf8bcb82ae697a5bac94bfbe93c3ad9d7487795.tar.bz2 luarocks-acf8bcb82ae697a5bac94bfbe93c3ad9d7487795.zip |
dependency pinning: luarocks.lock file and --pin flag
This adds support for pinning dependencies in projects and rocks:
* Adds a new flag called `--pin` which creates a `luarocks.lock`
when building a rock with `luarocks build` or `luarocks make`.
This lock file contains the exact version numbers of every
direct or indirect dependency of the rock (in other words,
it is the transitive closure of the dependencies.)
For `make`, the `luarocks.lock` file is created in the current
directory.
The lock file is also installed as part of the rock in
its metadata directory alongside its rockspec.
When using `--pin`, if a lock file already exists, it is
ignored and overwritten.
* When building a rock with `luarocks make`, if there is a
`luarocks.lock` file in the current directory, the exact
versions specified there will be used for resolving dependencies.
* When building a rock with `luarocks build`, if there is a
`luarocks.lock` file in root of its sources, the exact
versions specified there will be used for resolving dependencies.
* When installing a `.rock` file with `luarocks install`, if the
rock contains a `luarocks.lock` file (i.e., if its dependencies
were pinned with `--pin` when the rock was built), the exact
versions specified there will be used for resolving dependencies.
-rw-r--r-- | spec/build_spec.lua | 41 | ||||
-rw-r--r-- | spec/doc_spec.lua | 2 | ||||
-rw-r--r-- | spec/fixtures/a_repo/a_rock-2.0-1.src.rock | bin | 0 -> 541 bytes | |||
-rw-r--r-- | spec/fixtures/a_repo/manifest | 5 | ||||
-rw-r--r-- | spec/fixtures/a_repo/manifest-5.1 | 5 | ||||
-rw-r--r-- | spec/fixtures/a_repo/manifest-5.1.zip | bin | 350 -> 358 bytes | |||
-rw-r--r-- | spec/fixtures/a_repo/manifest-5.2 | 5 | ||||
-rw-r--r-- | spec/fixtures/a_repo/manifest-5.2.zip | bin | 350 -> 358 bytes | |||
-rw-r--r-- | spec/fixtures/a_repo/manifest-5.3 | 5 | ||||
-rw-r--r-- | spec/fixtures/a_repo/manifest-5.3.zip | bin | 350 -> 358 bytes | |||
-rw-r--r-- | spec/install_spec.lua | 44 | ||||
-rw-r--r-- | spec/make_spec.lua | 119 | ||||
-rw-r--r-- | src/luarocks/build.lua | 25 | ||||
-rw-r--r-- | src/luarocks/cmd/build.lua | 11 | ||||
-rw-r--r-- | src/luarocks/cmd/install.lua | 4 | ||||
-rw-r--r-- | src/luarocks/cmd/make.lua | 8 | ||||
-rw-r--r-- | src/luarocks/core/manif.lua | 2 | ||||
-rw-r--r-- | src/luarocks/core/persist.lua | 4 | ||||
-rw-r--r-- | src/luarocks/deplocks.lua | 106 | ||||
-rw-r--r-- | src/luarocks/deps.lua | 316 | ||||
-rw-r--r-- | src/luarocks/persist.lua | 3 | ||||
-rw-r--r-- | src/luarocks/test/busted.lua | 2 |
22 files changed, 590 insertions, 117 deletions
diff --git a/spec/build_spec.lua b/spec/build_spec.lua index eeca75cf..d64ace4d 100644 --- a/spec/build_spec.lua +++ b/spec/build_spec.lua | |||
@@ -116,11 +116,11 @@ describe("LuaRocks build #integration", function() | |||
116 | end) | 116 | end) |
117 | 117 | ||
118 | it("with --only-sources", function() | 118 | it("with --only-sources", function() |
119 | assert.is_true(run.luarocks_bool("download --server=" .. testing_paths.fixtures_dir .. "/a_repo --rockspec a_rock")) | 119 | assert.is_true(run.luarocks_bool("download --server=" .. testing_paths.fixtures_dir .. "/a_repo --rockspec a_rock 1.0")) |
120 | assert.is_false(run.luarocks_bool("build --only-sources=\"http://example.com\" a_rock-1.0-1.rockspec")) | 120 | assert.is_false(run.luarocks_bool("build --only-sources=\"http://example.com\" a_rock-1.0-1.rockspec")) |
121 | assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) | 121 | assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) |
122 | 122 | ||
123 | assert.is_true(run.luarocks_bool("download --server=" .. testing_paths.fixtures_dir .. "/a_repo --source a_rock")) | 123 | assert.is_true(run.luarocks_bool("download --server=" .. testing_paths.fixtures_dir .. "/a_repo --source a_rock 1.0")) |
124 | assert.is_true(run.luarocks_bool("build --only-sources=\"http://example.com\" a_rock-1.0-1.src.rock")) | 124 | assert.is_true(run.luarocks_bool("build --only-sources=\"http://example.com\" a_rock-1.0-1.src.rock")) |
125 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) | 125 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) |
126 | 126 | ||
@@ -199,7 +199,42 @@ describe("LuaRocks build #integration", function() | |||
199 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/test/1.0-1/test-1.0-1.rockspec")) | 199 | assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/test/1.0-1/test-1.0-1.rockspec")) |
200 | end) | 200 | end) |
201 | end) | 201 | end) |
202 | 202 | ||
203 | it("supports --pin #pinning", function() | ||
204 | test_env.run_in_tmp(function(tmpdir) | ||
205 | write_file("test-1.0-1.rockspec", [[ | ||
206 | package = "test" | ||
207 | version = "1.0-1" | ||
208 | source = { | ||
209 | url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" | ||
210 | } | ||
211 | dependencies = { | ||
212 | "a_rock >= 0.8" | ||
213 | } | ||
214 | build = { | ||
215 | type = "builtin", | ||
216 | modules = { | ||
217 | test = "test.lua" | ||
218 | } | ||
219 | } | ||
220 | ]], finally) | ||
221 | write_file("test.lua", "return {}", finally) | ||
222 | |||
223 | assert.is_true(run.luarocks_bool("build --server=" .. testing_paths.fixtures_dir .. "/a_repo test-1.0-1.rockspec --pin --tree=lua_modules")) | ||
224 | assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/test-1.0-1.rockspec")) | ||
225 | assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/a_rock/2.0-1/a_rock-2.0-1.rockspec")) | ||
226 | local lockfilename = "./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/luarocks.lock" | ||
227 | assert.is.truthy(lfs.attributes(lockfilename)) | ||
228 | local lockdata = loadfile(lockfilename)() | ||
229 | assert.same({ | ||
230 | dependencies = { | ||
231 | ["a_rock"] = "2.0-1", | ||
232 | ["lua"] = test_env.lua_version .. "-1", | ||
233 | } | ||
234 | }, lockdata) | ||
235 | end) | ||
236 | end) | ||
237 | |||
203 | it("lmathx deps partial match", function() | 238 | it("lmathx deps partial match", function() |
204 | assert.is_true(run.luarocks_bool("build lmathx")) | 239 | assert.is_true(run.luarocks_bool("build lmathx")) |
205 | 240 | ||
diff --git a/spec/doc_spec.lua b/spec/doc_spec.lua index bf5214d4..2c0f4bce 100644 --- a/spec/doc_spec.lua +++ b/spec/doc_spec.lua | |||
@@ -70,7 +70,7 @@ describe("LuaRocks doc tests #integration", function() | |||
70 | describe("#namespaces", function() | 70 | describe("#namespaces", function() |
71 | it("retrieves docs for a namespaced package from the command-line", function() | 71 | it("retrieves docs for a namespaced package from the command-line", function() |
72 | assert(run.luarocks_bool("build a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) | 72 | assert(run.luarocks_bool("build a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) |
73 | assert(run.luarocks_bool("build a_rock --keep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) | 73 | assert(run.luarocks_bool("build a_rock 1.0 --keep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) |
74 | assert.match("a_rock 2.0", run.luarocks("doc a_user/a_rock")) | 74 | assert.match("a_rock 2.0", run.luarocks("doc a_user/a_rock")) |
75 | end) | 75 | end) |
76 | end) | 76 | end) |
diff --git a/spec/fixtures/a_repo/a_rock-2.0-1.src.rock b/spec/fixtures/a_repo/a_rock-2.0-1.src.rock new file mode 100644 index 00000000..5824c767 --- /dev/null +++ b/spec/fixtures/a_repo/a_rock-2.0-1.src.rock | |||
Binary files differ | |||
diff --git a/spec/fixtures/a_repo/manifest b/spec/fixtures/a_repo/manifest index 3b01b427..5ab87d25 100644 --- a/spec/fixtures/a_repo/manifest +++ b/spec/fixtures/a_repo/manifest | |||
@@ -19,6 +19,11 @@ repository = { | |||
19 | { | 19 | { |
20 | arch = "rockspec" | 20 | arch = "rockspec" |
21 | } | 21 | } |
22 | }, | ||
23 | ["2.0-1"] = { | ||
24 | { | ||
25 | arch = "src" | ||
26 | } | ||
22 | } | 27 | } |
23 | }, | 28 | }, |
24 | busted_project = { | 29 | busted_project = { |
diff --git a/spec/fixtures/a_repo/manifest-5.1 b/spec/fixtures/a_repo/manifest-5.1 index 3b01b427..5ab87d25 100644 --- a/spec/fixtures/a_repo/manifest-5.1 +++ b/spec/fixtures/a_repo/manifest-5.1 | |||
@@ -19,6 +19,11 @@ repository = { | |||
19 | { | 19 | { |
20 | arch = "rockspec" | 20 | arch = "rockspec" |
21 | } | 21 | } |
22 | }, | ||
23 | ["2.0-1"] = { | ||
24 | { | ||
25 | arch = "src" | ||
26 | } | ||
22 | } | 27 | } |
23 | }, | 28 | }, |
24 | busted_project = { | 29 | busted_project = { |
diff --git a/spec/fixtures/a_repo/manifest-5.1.zip b/spec/fixtures/a_repo/manifest-5.1.zip index 7b53aeb0..65e316df 100644 --- a/spec/fixtures/a_repo/manifest-5.1.zip +++ b/spec/fixtures/a_repo/manifest-5.1.zip | |||
Binary files differ | |||
diff --git a/spec/fixtures/a_repo/manifest-5.2 b/spec/fixtures/a_repo/manifest-5.2 index 3b01b427..5ab87d25 100644 --- a/spec/fixtures/a_repo/manifest-5.2 +++ b/spec/fixtures/a_repo/manifest-5.2 | |||
@@ -19,6 +19,11 @@ repository = { | |||
19 | { | 19 | { |
20 | arch = "rockspec" | 20 | arch = "rockspec" |
21 | } | 21 | } |
22 | }, | ||
23 | ["2.0-1"] = { | ||
24 | { | ||
25 | arch = "src" | ||
26 | } | ||
22 | } | 27 | } |
23 | }, | 28 | }, |
24 | busted_project = { | 29 | busted_project = { |
diff --git a/spec/fixtures/a_repo/manifest-5.2.zip b/spec/fixtures/a_repo/manifest-5.2.zip index d2eddc40..b4334a65 100644 --- a/spec/fixtures/a_repo/manifest-5.2.zip +++ b/spec/fixtures/a_repo/manifest-5.2.zip | |||
Binary files differ | |||
diff --git a/spec/fixtures/a_repo/manifest-5.3 b/spec/fixtures/a_repo/manifest-5.3 index 3b01b427..5ab87d25 100644 --- a/spec/fixtures/a_repo/manifest-5.3 +++ b/spec/fixtures/a_repo/manifest-5.3 | |||
@@ -19,6 +19,11 @@ repository = { | |||
19 | { | 19 | { |
20 | arch = "rockspec" | 20 | arch = "rockspec" |
21 | } | 21 | } |
22 | }, | ||
23 | ["2.0-1"] = { | ||
24 | { | ||
25 | arch = "src" | ||
26 | } | ||
22 | } | 27 | } |
23 | }, | 28 | }, |
24 | busted_project = { | 29 | busted_project = { |
diff --git a/spec/fixtures/a_repo/manifest-5.3.zip b/spec/fixtures/a_repo/manifest-5.3.zip index 686fe232..bab15712 100644 --- a/spec/fixtures/a_repo/manifest-5.3.zip +++ b/spec/fixtures/a_repo/manifest-5.3.zip | |||
Binary files differ | |||
diff --git a/spec/install_spec.lua b/spec/install_spec.lua index bf50ced7..76dc2201 100644 --- a/spec/install_spec.lua +++ b/spec/install_spec.lua | |||
@@ -267,6 +267,50 @@ describe("luarocks install #integration", function() | |||
267 | end) | 267 | end) |
268 | end) | 268 | end) |
269 | 269 | ||
270 | it("respects luarocks.lock in package #pinning", function() | ||
271 | test_env.run_in_tmp(function(tmpdir) | ||
272 | write_file("test-1.0-1.rockspec", [[ | ||
273 | package = "test" | ||
274 | version = "1.0-1" | ||
275 | source = { | ||
276 | url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" | ||
277 | } | ||
278 | dependencies = { | ||
279 | "a_rock >= 0.8" | ||
280 | } | ||
281 | build = { | ||
282 | type = "builtin", | ||
283 | modules = { | ||
284 | test = "test.lua" | ||
285 | } | ||
286 | } | ||
287 | ]], finally) | ||
288 | write_file("test.lua", "return {}", finally) | ||
289 | write_file("luarocks.lock", [[ | ||
290 | return { | ||
291 | dependencies = { | ||
292 | ["a_rock"] = "1.0-1", | ||
293 | } | ||
294 | } | ||
295 | ]], finally) | ||
296 | |||
297 | assert.is_true(run.luarocks_bool("make --pack-binary-rock --server=" .. testing_paths.fixtures_dir .. "/a_repo test-1.0-1.rockspec")) | ||
298 | assert.is_true(os.remove("luarocks.lock")) | ||
299 | |||
300 | assert.is.truthy(lfs.attributes("./test-1.0-1.all.rock")) | ||
301 | |||
302 | assert.is.falsy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/test-1.0-1.rockspec")) | ||
303 | assert.is.falsy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) | ||
304 | |||
305 | print(run.luarocks("install ./test-1.0-1.all.rock --tree=lua_modules --server=" .. testing_paths.fixtures_dir .. "/a_repo")) | ||
306 | |||
307 | assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/test-1.0-1.rockspec")) | ||
308 | assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/luarocks.lock")) | ||
309 | assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) | ||
310 | assert.is.falsy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/a_rock/2.0-1")) | ||
311 | end) | ||
312 | end) | ||
313 | |||
270 | describe("#unix install runs build from #git", function() | 314 | describe("#unix install runs build from #git", function() |
271 | local git | 315 | local git |
272 | 316 | ||
diff --git a/spec/make_spec.lua b/spec/make_spec.lua index 5ec99fa7..8baa3561 100644 --- a/spec/make_spec.lua +++ b/spec/make_spec.lua | |||
@@ -3,6 +3,7 @@ local lfs = require("lfs") | |||
3 | local run = test_env.run | 3 | local run = test_env.run |
4 | local testing_paths = test_env.testing_paths | 4 | local testing_paths = test_env.testing_paths |
5 | local env_variables = test_env.env_variables | 5 | local env_variables = test_env.env_variables |
6 | local write_file = test_env.write_file | ||
6 | 7 | ||
7 | test_env.unload_luarocks() | 8 | test_env.unload_luarocks() |
8 | 9 | ||
@@ -125,6 +126,124 @@ describe("LuaRocks make tests #integration", function() | |||
125 | end) | 126 | end) |
126 | end) | 127 | end) |
127 | 128 | ||
129 | it("supports --pin #pinning", function() | ||
130 | test_env.run_in_tmp(function(tmpdir) | ||
131 | write_file("test-1.0-1.rockspec", [[ | ||
132 | package = "test" | ||
133 | version = "1.0-1" | ||
134 | source = { | ||
135 | url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" | ||
136 | } | ||
137 | dependencies = { | ||
138 | "a_rock 1.0" | ||
139 | } | ||
140 | build = { | ||
141 | type = "builtin", | ||
142 | modules = { | ||
143 | test = "test.lua" | ||
144 | } | ||
145 | } | ||
146 | ]], finally) | ||
147 | write_file("test.lua", "return {}", finally) | ||
148 | |||
149 | assert.is_true(run.luarocks_bool("make --server=" .. testing_paths.fixtures_dir .. "/a_repo --pin --tree=lua_modules")) | ||
150 | assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/test-1.0-1.rockspec")) | ||
151 | assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) | ||
152 | local lockfilename = "./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/luarocks.lock" | ||
153 | assert.is.truthy(lfs.attributes(lockfilename)) | ||
154 | local lockdata = loadfile(lockfilename)() | ||
155 | assert.same({ | ||
156 | dependencies = { | ||
157 | ["a_rock"] = "1.0-1", | ||
158 | ["lua"] = test_env.lua_version .. "-1", | ||
159 | } | ||
160 | }, lockdata) | ||
161 | end) | ||
162 | end) | ||
163 | |||
164 | it("respects luarocks.lock when present #pinning", function() | ||
165 | test_env.run_in_tmp(function(tmpdir) | ||
166 | write_file("test-2.0-1.rockspec", [[ | ||
167 | package = "test" | ||
168 | version = "2.0-1" | ||
169 | source = { | ||
170 | url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" | ||
171 | } | ||
172 | dependencies = { | ||
173 | "a_rock >= 0.8" | ||
174 | } | ||
175 | build = { | ||
176 | type = "builtin", | ||
177 | modules = { | ||
178 | test = "test.lua" | ||
179 | } | ||
180 | } | ||
181 | ]], finally) | ||
182 | write_file("test.lua", "return {}", finally) | ||
183 | write_file("luarocks.lock", [[ | ||
184 | return { | ||
185 | dependencies = { | ||
186 | ["a_rock"] = "1.0-1", | ||
187 | } | ||
188 | } | ||
189 | ]], finally) | ||
190 | |||
191 | print(run.luarocks("make --server=" .. testing_paths.fixtures_dir .. "/a_repo --tree=lua_modules")) | ||
192 | assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/2.0-1/test-2.0-1.rockspec")) | ||
193 | assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) | ||
194 | local lockfilename = "./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/2.0-1/luarocks.lock" | ||
195 | assert.is.truthy(lfs.attributes(lockfilename)) | ||
196 | local lockdata = loadfile(lockfilename)() | ||
197 | assert.same({ | ||
198 | dependencies = { | ||
199 | ["a_rock"] = "1.0-1", | ||
200 | } | ||
201 | }, lockdata) | ||
202 | end) | ||
203 | end) | ||
204 | |||
205 | it("overrides luarocks.lock with --pin #pinning", function() | ||
206 | test_env.run_in_tmp(function(tmpdir) | ||
207 | write_file("test-2.0-1.rockspec", [[ | ||
208 | package = "test" | ||
209 | version = "2.0-1" | ||
210 | source = { | ||
211 | url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" | ||
212 | } | ||
213 | dependencies = { | ||
214 | "a_rock >= 0.8" | ||
215 | } | ||
216 | build = { | ||
217 | type = "builtin", | ||
218 | modules = { | ||
219 | test = "test.lua" | ||
220 | } | ||
221 | } | ||
222 | ]], finally) | ||
223 | write_file("test.lua", "return {}", finally) | ||
224 | write_file("luarocks.lock", [[ | ||
225 | return { | ||
226 | dependencies = { | ||
227 | ["a_rock"] = "1.0-1", | ||
228 | } | ||
229 | } | ||
230 | ]], finally) | ||
231 | |||
232 | print(run.luarocks("make --server=" .. testing_paths.fixtures_dir .. "/a_repo --tree=lua_modules --pin")) | ||
233 | assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/2.0-1/test-2.0-1.rockspec")) | ||
234 | assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/a_rock/2.0-1/a_rock-2.0-1.rockspec")) | ||
235 | local lockfilename = "./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/2.0-1/luarocks.lock" | ||
236 | assert.is.truthy(lfs.attributes(lockfilename)) | ||
237 | local lockdata = loadfile(lockfilename)() | ||
238 | assert.same({ | ||
239 | dependencies = { | ||
240 | ["a_rock"] = "2.0-1", | ||
241 | ["lua"] = test_env.lua_version .. "-1", | ||
242 | } | ||
243 | }, lockdata) | ||
244 | end) | ||
245 | end) | ||
246 | |||
128 | describe("#ddt LuaRocks make upgrading rockspecs with double deploy types", function() | 247 | describe("#ddt LuaRocks make upgrading rockspecs with double deploy types", function() |
129 | local deploy_lib_dir = testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION | 248 | local deploy_lib_dir = testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION |
130 | local deploy_lua_dir = testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION | 249 | local deploy_lua_dir = testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION |
diff --git a/src/luarocks/build.lua b/src/luarocks/build.lua index 9aa70345..ca0237b7 100644 --- a/src/luarocks/build.lua +++ b/src/luarocks/build.lua | |||
@@ -11,6 +11,7 @@ local deps = require("luarocks.deps") | |||
11 | local cfg = require("luarocks.core.cfg") | 11 | local cfg = require("luarocks.core.cfg") |
12 | local repos = require("luarocks.repos") | 12 | local repos = require("luarocks.repos") |
13 | local writer = require("luarocks.manif.writer") | 13 | local writer = require("luarocks.manif.writer") |
14 | local deplocks = require("luarocks.deplocks") | ||
14 | 15 | ||
15 | build.opts = util.opts_table("build.opts", { | 16 | build.opts = util.opts_table("build.opts", { |
16 | need_to_fetch = "boolean", | 17 | need_to_fetch = "boolean", |
@@ -21,6 +22,7 @@ build.opts = util.opts_table("build.opts", { | |||
21 | branch = "string?", | 22 | branch = "string?", |
22 | verify = "boolean", | 23 | verify = "boolean", |
23 | check_lua_versions = "boolean", | 24 | check_lua_versions = "boolean", |
25 | pin = "boolean", | ||
24 | }) | 26 | }) |
25 | 27 | ||
26 | do | 28 | do |
@@ -125,6 +127,7 @@ local function process_dependencies(rockspec, opts) | |||
125 | if opts.deps_mode == "none" then | 127 | if opts.deps_mode == "none" then |
126 | return true | 128 | return true |
127 | end | 129 | end |
130 | |||
128 | if not opts.build_only_deps then | 131 | if not opts.build_only_deps then |
129 | if next(rockspec.build_dependencies) then | 132 | if next(rockspec.build_dependencies) then |
130 | local ok, err, errcode = deps.fulfill_dependencies(rockspec, "build_dependencies", opts.deps_mode, opts.verify) | 133 | local ok, err, errcode = deps.fulfill_dependencies(rockspec, "build_dependencies", opts.deps_mode, opts.verify) |
@@ -326,6 +329,11 @@ local function write_rock_dir_files(rockspec, opts) | |||
326 | local name, version = rockspec.name, rockspec.version | 329 | local name, version = rockspec.name, rockspec.version |
327 | 330 | ||
328 | fs.copy(rockspec.local_abs_filename, path.rockspec_file(name, version), "read") | 331 | fs.copy(rockspec.local_abs_filename, path.rockspec_file(name, version), "read") |
332 | |||
333 | local deplock_file = deplocks.get_abs_filename(rockspec.name) | ||
334 | if deplock_file then | ||
335 | fs.copy(deplock_file, dir.path(path.install_dir(name, version), "luarocks.lock"), "read") | ||
336 | end | ||
329 | 337 | ||
330 | local ok, err = writer.make_rock_manifest(name, version) | 338 | local ok, err = writer.make_rock_manifest(name, version) |
331 | if not ok then return nil, err end | 339 | if not ok then return nil, err end |
@@ -362,7 +370,14 @@ function build.build_rockspec(rockspec, opts) | |||
362 | end | 370 | end |
363 | end | 371 | end |
364 | 372 | ||
365 | local ok, err = process_dependencies(rockspec, opts) | 373 | local ok, err = fetch_and_change_to_source_dir(rockspec, opts) |
374 | if not ok then return nil, err end | ||
375 | |||
376 | if opts.pin then | ||
377 | deplocks.init(rockspec.name, ".") | ||
378 | end | ||
379 | |||
380 | ok, err = process_dependencies(rockspec, opts) | ||
366 | if not ok then return nil, err end | 381 | if not ok then return nil, err end |
367 | 382 | ||
368 | local name, version = rockspec.name, rockspec.version | 383 | local name, version = rockspec.name, rockspec.version |
@@ -373,10 +388,6 @@ function build.build_rockspec(rockspec, opts) | |||
373 | if repos.is_installed(name, version) then | 388 | if repos.is_installed(name, version) then |
374 | repos.delete_version(name, version, opts.deps_mode) | 389 | repos.delete_version(name, version, opts.deps_mode) |
375 | end | 390 | end |
376 | |||
377 | ok, err = fetch_and_change_to_source_dir(rockspec, opts) | ||
378 | if not ok then return nil, err end | ||
379 | |||
380 | local dirs, err = prepare_install_dirs(name, version) | 391 | local dirs, err = prepare_install_dirs(name, version) |
381 | if not dirs then return nil, err end | 392 | if not dirs then return nil, err end |
382 | 393 | ||
@@ -406,6 +417,10 @@ function build.build_rockspec(rockspec, opts) | |||
406 | fs.pop_dir() | 417 | fs.pop_dir() |
407 | end | 418 | end |
408 | 419 | ||
420 | if opts.pin then | ||
421 | deplocks.write_file() | ||
422 | end | ||
423 | |||
409 | ok, err = write_rock_dir_files(rockspec, opts) | 424 | ok, err = write_rock_dir_files(rockspec, opts) |
410 | if not ok then return nil, err end | 425 | if not ok then return nil, err end |
411 | 426 | ||
diff --git a/src/luarocks/cmd/build.lua b/src/luarocks/cmd/build.lua index 6b30666b..3bc1554e 100644 --- a/src/luarocks/cmd/build.lua +++ b/src/luarocks/cmd/build.lua | |||
@@ -19,6 +19,8 @@ local cmd = require("luarocks.cmd") | |||
19 | 19 | ||
20 | function cmd_build.add_to_parser(parser) | 20 | function cmd_build.add_to_parser(parser) |
21 | local cmd = parser:command("build", "Build and install a rock, compiling its C parts if any.\n".. | 21 | local cmd = parser:command("build", "Build and install a rock, compiling its C parts if any.\n".. |
22 | "If the sources contain a luarocks.lock file, uses it as an authoritative source for ".. | ||
23 | "exact version of dependencies.\n".. | ||
22 | "If no arguments are given, behaves as luarocks make.", util.see_also()) | 24 | "If no arguments are given, behaves as luarocks make.", util.see_also()) |
23 | :summary("Build/compile a rock.") | 25 | :summary("Build/compile a rock.") |
24 | 26 | ||
@@ -33,6 +35,10 @@ function cmd_build.add_to_parser(parser) | |||
33 | "rockspec. Allows to specify a different branch to fetch. Particularly ".. | 35 | "rockspec. Allows to specify a different branch to fetch. Particularly ".. |
34 | 'for "dev" rocks.') | 36 | 'for "dev" rocks.') |
35 | :argname("<name>") | 37 | :argname("<name>") |
38 | parser:flag("--pin", "Create a luarocks.lock file listing the exact ".. | ||
39 | "versions of each dependency found for this rock (recursively), ".. | ||
40 | "and store it in the rock's directory. ".. | ||
41 | "Ignores any existing luarocks.lock file in the rock's sources.") | ||
36 | make.cmd_options(cmd) | 42 | make.cmd_options(cmd) |
37 | end | 43 | end |
38 | 44 | ||
@@ -124,6 +130,7 @@ function cmd_build.command(args) | |||
124 | branch = args.branch, | 130 | branch = args.branch, |
125 | verify = not not args.verify, | 131 | verify = not not args.verify, |
126 | check_lua_versions = not not args.check_lua_versions, | 132 | check_lua_versions = not not args.check_lua_versions, |
133 | pin = not not args.pin, | ||
127 | }) | 134 | }) |
128 | 135 | ||
129 | if args.sign and not args.pack_binary_rock then | 136 | if args.sign and not args.pack_binary_rock then |
@@ -167,7 +174,9 @@ function cmd_build.command(args) | |||
167 | end | 174 | end |
168 | end | 175 | end |
169 | 176 | ||
170 | writer.check_dependencies(nil, deps.get_deps_mode(args)) | 177 | if opts.deps_mode ~= "none" then |
178 | writer.check_dependencies(nil, deps.get_deps_mode(args)) | ||
179 | end | ||
171 | return name, version | 180 | return name, version |
172 | end | 181 | end |
173 | 182 | ||
diff --git a/src/luarocks/cmd/install.lua b/src/luarocks/cmd/install.lua index cd1df294..ad2a5ea7 100644 --- a/src/luarocks/cmd/install.lua +++ b/src/luarocks/cmd/install.lua | |||
@@ -114,7 +114,7 @@ function install.install_binary_rock(rock_file, opts) | |||
114 | end | 114 | end |
115 | 115 | ||
116 | if deps_mode ~= "none" then | 116 | if deps_mode ~= "none" then |
117 | ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", deps_mode, opts.verify) | 117 | ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", deps_mode, opts.verify, install_dir) |
118 | if err then return nil, err, errcode end | 118 | if err then return nil, err, errcode end |
119 | end | 119 | end |
120 | 120 | ||
@@ -163,7 +163,7 @@ function install.install_binary_rock_deps(rock_file, opts) | |||
163 | return nil, "Failed loading rockspec for installed package: "..err, errcode | 163 | return nil, "Failed loading rockspec for installed package: "..err, errcode |
164 | end | 164 | end |
165 | 165 | ||
166 | ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", opts.deps_mode, opts.verify) | 166 | ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", opts.deps_mode, opts.verify, install_dir) |
167 | if err then return nil, err, errcode end | 167 | if err then return nil, err, errcode end |
168 | 168 | ||
169 | util.printout() | 169 | util.printout() |
diff --git a/src/luarocks/cmd/make.lua b/src/luarocks/cmd/make.lua index 74de6f26..a2ae4cd0 100644 --- a/src/luarocks/cmd/make.lua +++ b/src/luarocks/cmd/make.lua | |||
@@ -13,6 +13,7 @@ local fetch = require("luarocks.fetch") | |||
13 | local pack = require("luarocks.pack") | 13 | local pack = require("luarocks.pack") |
14 | local remove = require("luarocks.remove") | 14 | local remove = require("luarocks.remove") |
15 | local deps = require("luarocks.deps") | 15 | local deps = require("luarocks.deps") |
16 | local deplocks = require("luarocks.deplocks") | ||
16 | local writer = require("luarocks.manif.writer") | 17 | local writer = require("luarocks.manif.writer") |
17 | local cmd = require("luarocks.cmd") | 18 | local cmd = require("luarocks.cmd") |
18 | 19 | ||
@@ -37,6 +38,8 @@ function make.cmd_options(parser) | |||
37 | "signature file for the generated .rock file.") | 38 | "signature file for the generated .rock file.") |
38 | parser:flag("--check-lua-versions", "If the rock can't be found, check repository ".. | 39 | parser:flag("--check-lua-versions", "If the rock can't be found, check repository ".. |
39 | "and report if it is available for another Lua version.") | 40 | "and report if it is available for another Lua version.") |
41 | parser:flag("--pin", "Pin the exact dependencies used for the rockspec".. | ||
42 | "being built into a luarocks.lock file in the current directory.") | ||
40 | util.deps_mode_option(parser) | 43 | util.deps_mode_option(parser) |
41 | end | 44 | end |
42 | 45 | ||
@@ -54,6 +57,10 @@ This command is useful as a tool for debugging rockspecs. | |||
54 | To install rocks, you'll normally want to use the "install" and "build" | 57 | To install rocks, you'll normally want to use the "install" and "build" |
55 | commands. See the help on those for details. | 58 | commands. See the help on those for details. |
56 | 59 | ||
60 | If the current directory contains a luarocks.lock file, it is used as the | ||
61 | authoritative source for exact version of dependencies. The --pin flag | ||
62 | overrides and recreates this file scanning dependency based on ranges. | ||
63 | |||
57 | NB: Use `luarocks install` with the `--only-deps` flag if you want to install | 64 | NB: Use `luarocks install` with the `--only-deps` flag if you want to install |
58 | only dependencies of the rockspec (see `luarocks help install`). | 65 | only dependencies of the rockspec (see `luarocks help install`). |
59 | ]], util.see_also()) | 66 | ]], util.see_also()) |
@@ -97,6 +104,7 @@ function make.command(args) | |||
97 | branch = args.branch, | 104 | branch = args.branch, |
98 | verify = not not args.verify, | 105 | verify = not not args.verify, |
99 | check_lua_versions = not not args.check_lua_versions, | 106 | check_lua_versions = not not args.check_lua_versions, |
107 | pin = not not args.pin | ||
100 | }) | 108 | }) |
101 | 109 | ||
102 | if args.sign and not args.pack_binary_rock then | 110 | if args.sign and not args.pack_binary_rock then |
diff --git a/src/luarocks/core/manif.lua b/src/luarocks/core/manif.lua index 4fd35c6c..1e9da75e 100644 --- a/src/luarocks/core/manif.lua +++ b/src/luarocks/core/manif.lua | |||
@@ -102,7 +102,7 @@ function manif.scan_dependencies(name, version, tree_manifests, dest) | |||
102 | if entries then | 102 | if entries then |
103 | for ver, _ in util.sortedpairs(entries, vers.compare_versions) do | 103 | for ver, _ in util.sortedpairs(entries, vers.compare_versions) do |
104 | if (not constraints) or vers.match_constraints(vers.parse_version(ver), constraints) then | 104 | if (not constraints) or vers.match_constraints(vers.parse_version(ver), constraints) then |
105 | manif.scan_dependencies(pkg, version, tree_manifests, dest) | 105 | manif.scan_dependencies(pkg, ver, tree_manifests, dest) |
106 | end | 106 | end |
107 | end | 107 | end |
108 | end | 108 | end |
diff --git a/src/luarocks/core/persist.lua b/src/luarocks/core/persist.lua index 48979184..59089818 100644 --- a/src/luarocks/core/persist.lua +++ b/src/luarocks/core/persist.lua | |||
@@ -10,7 +10,7 @@ local require = nil | |||
10 | -- @return (true, any) or (nil, string, string): true and the return value | 10 | -- @return (true, any) or (nil, string, string): true and the return value |
11 | -- of the file, or nil, an error message and an error code ("open", "load" | 11 | -- of the file, or nil, an error message and an error code ("open", "load" |
12 | -- or "run") in case of errors. | 12 | -- or "run") in case of errors. |
13 | local function run_file(filename, env) | 13 | function persist.run_file(filename, env) |
14 | local fd, err = io.open(filename) | 14 | local fd, err = io.open(filename) |
15 | if not fd then | 15 | if not fd then |
16 | return nil, err, "open" | 16 | return nil, err, "open" |
@@ -67,7 +67,7 @@ function persist.load_into_table(filename, tbl) | |||
67 | local save_mt = getmetatable(result) | 67 | local save_mt = getmetatable(result) |
68 | setmetatable(result, globals_mt) | 68 | setmetatable(result, globals_mt) |
69 | 69 | ||
70 | local ok, err, errcode = run_file(filename, result) | 70 | local ok, err, errcode = persist.run_file(filename, result) |
71 | 71 | ||
72 | setmetatable(result, save_mt) | 72 | setmetatable(result, save_mt) |
73 | 73 | ||
diff --git a/src/luarocks/deplocks.lua b/src/luarocks/deplocks.lua new file mode 100644 index 00000000..f6449986 --- /dev/null +++ b/src/luarocks/deplocks.lua | |||
@@ -0,0 +1,106 @@ | |||
1 | local deplocks = {} | ||
2 | |||
3 | local fs = require("luarocks.fs") | ||
4 | local dir = require("luarocks.dir") | ||
5 | local util = require("luarocks.util") | ||
6 | local persist = require("luarocks.persist") | ||
7 | |||
8 | local deptable = {} | ||
9 | local deptable_mode = "start" | ||
10 | local deplock_abs_filename | ||
11 | local deplock_root_rock_name | ||
12 | |||
13 | function deplocks.init(root_rock_name, dirname) | ||
14 | if deptable_mode ~= "start" then | ||
15 | return | ||
16 | end | ||
17 | deptable_mode = "create" | ||
18 | |||
19 | local filename = dir.path(dirname, "luarocks.lock") | ||
20 | deplock_abs_filename = fs.absolute_name(filename) | ||
21 | deplock_root_rock_name = root_rock_name | ||
22 | |||
23 | deptable = {} | ||
24 | end | ||
25 | |||
26 | function deplocks.get_abs_filename(root_rock_name) | ||
27 | if root_rock_name == deplock_root_rock_name then | ||
28 | return deplock_abs_filename | ||
29 | end | ||
30 | end | ||
31 | |||
32 | function deplocks.load(root_rock_name, dirname) | ||
33 | if deptable_mode ~= "start" then | ||
34 | return true, nil | ||
35 | end | ||
36 | deptable_mode = "locked" | ||
37 | |||
38 | local filename = dir.path(dirname, "luarocks.lock") | ||
39 | local ok, result, errcode = persist.run_file(filename, {}) | ||
40 | if errcode == "load" or errcode == "run" then | ||
41 | -- bad config file or depends on env, so error out | ||
42 | return nil, nil, "Could not read existing lockfile " .. filename | ||
43 | end | ||
44 | |||
45 | if errcode == "open" then | ||
46 | -- could not open, maybe file does not exist | ||
47 | return true, nil | ||
48 | end | ||
49 | |||
50 | deplock_abs_filename = fs.absolute_name(filename) | ||
51 | deplock_root_rock_name = root_rock_name | ||
52 | |||
53 | deptable = result | ||
54 | return true, filename | ||
55 | end | ||
56 | |||
57 | function deplocks.add(depskey, name, version) | ||
58 | if deptable_mode == "locked" then | ||
59 | return | ||
60 | end | ||
61 | |||
62 | local dk = deptable[depskey] | ||
63 | if not dk then | ||
64 | dk = {} | ||
65 | deptable[depskey] = dk | ||
66 | end | ||
67 | |||
68 | if not dk[name] then | ||
69 | dk[name] = version | ||
70 | end | ||
71 | end | ||
72 | |||
73 | function deplocks.get(depskey, name) | ||
74 | local dk = deptable[depskey] | ||
75 | if not dk then | ||
76 | return nil | ||
77 | end | ||
78 | |||
79 | return deptable[name] | ||
80 | end | ||
81 | |||
82 | function deplocks.write_file() | ||
83 | if deptable_mode ~= "create" then | ||
84 | return true | ||
85 | end | ||
86 | |||
87 | return persist.save_as_module(deplock_abs_filename, deptable) | ||
88 | end | ||
89 | |||
90 | -- a table-like interface to deplocks | ||
91 | function deplocks.proxy(depskey) | ||
92 | return setmetatable({}, { | ||
93 | __index = function(_, k) | ||
94 | return deplocks.get(depskey, k) | ||
95 | end, | ||
96 | __newindex = function(_, k, v) | ||
97 | return deplocks.add(depskey, k, v) | ||
98 | end, | ||
99 | }) | ||
100 | end | ||
101 | |||
102 | function deplocks.each(depskey) | ||
103 | return util.sortedpairs(deptable[depskey] or {}) | ||
104 | end | ||
105 | |||
106 | return deplocks | ||
diff --git a/src/luarocks/deps.lua b/src/luarocks/deps.lua index 7f695d9c..d54c30de 100644 --- a/src/luarocks/deps.lua +++ b/src/luarocks/deps.lua | |||
@@ -11,64 +11,114 @@ local util = require("luarocks.util") | |||
11 | local vers = require("luarocks.core.vers") | 11 | local vers = require("luarocks.core.vers") |
12 | local queries = require("luarocks.queries") | 12 | local queries = require("luarocks.queries") |
13 | local builtin = require("luarocks.build.builtin") | 13 | local builtin = require("luarocks.build.builtin") |
14 | local deplocks = require("luarocks.deplocks") | ||
14 | 15 | ||
15 | --- Attempt to match a dependency to an installed rock. | 16 | --- Generate a function that matches dep queries against the manifest, |
16 | -- @param dep table: A dependency parsed in table format. | 17 | -- taking into account rocks_provided, the blacklist and the lockfile. |
17 | -- @param blacklist table: Versions that can't be accepted. Table where keys | 18 | -- @param deps_mode "one", "none", "all" or "order" |
18 | -- are program versions and values are 'true'. | 19 | -- @param rocks_provided a one-level table mapping names to versions, |
20 | -- listing rocks to consider provided by the VM | ||
19 | -- @param rocks_provided table: A table of auto-provided dependencies. | 21 | -- @param rocks_provided table: A table of auto-provided dependencies. |
20 | -- by this Lua implementation for the given dependency. | 22 | -- by this Lua implementation for the given dependency. |
21 | -- @return string or nil: latest installed version of the rock matching the dependency | 23 | -- @param depskey key to use when matching the lockfile ("dependencies", |
22 | -- or nil if it could not be matched. | 24 | -- "build_dependencies", etc.) |
23 | local function match_dep(dep, blacklist, deps_mode, rocks_provided) | 25 | -- @param blacklist a two-level table mapping names to versions to boolean, |
24 | assert(type(dep) == "table") | 26 | -- listing rocks to not match |
27 | -- @return function(dep): {string}, {string:string}, string, boolean | ||
28 | -- * array of matching versions | ||
29 | -- * map of versions to locations | ||
30 | -- * version matched via lockfile if any | ||
31 | -- * true if rock matched via rocks_provided | ||
32 | local function prepare_get_versions(deps_mode, rocks_provided, depskey, blacklist) | ||
33 | assert(type(deps_mode) == "string") | ||
25 | assert(type(rocks_provided) == "table") | 34 | assert(type(rocks_provided) == "table") |
26 | 35 | assert(type(depskey) == "string") | |
27 | local versions, locations | 36 | assert(type(blacklist) == "table" or blacklist == nil) |
28 | local provided = rocks_provided[dep.name] | 37 | |
29 | if provided then | 38 | return function(dep) |
30 | -- Provided rocks have higher priority than manifest's rocks. | 39 | local versions, locations |
31 | versions, locations = { provided }, {} | 40 | local provided = rocks_provided[dep.name] |
32 | else | 41 | if provided then |
33 | versions, locations = manif.get_versions(dep, deps_mode) | 42 | -- Provided rocks have higher priority than manifest's rocks. |
43 | versions, locations = { provided }, {} | ||
44 | else | ||
45 | if deps_mode == "none" then | ||
46 | deps_mode = "one" | ||
47 | end | ||
48 | versions, locations = manif.get_versions(dep, deps_mode) | ||
49 | end | ||
50 | |||
51 | if blacklist and blacklist[dep.name] then | ||
52 | local orig_versions = versions | ||
53 | versions = {} | ||
54 | for _, v in ipairs(orig_versions) do | ||
55 | if not blacklist[dep.name][v] then | ||
56 | table.insert(versions, v) | ||
57 | end | ||
58 | end | ||
59 | end | ||
60 | |||
61 | local lockversion = deplocks.get(depskey, dep.name) | ||
62 | |||
63 | return versions, locations, lockversion, provided ~= nil | ||
34 | end | 64 | end |
65 | end | ||
35 | 66 | ||
67 | --- Attempt to match a dependency to an installed rock. | ||
68 | -- @param blacklist table: Versions that can't be accepted. Table where keys | ||
69 | -- are program versions and values are 'true'. | ||
70 | -- @param get_versions a getter function obtained via prepare_get_versions | ||
71 | -- @return (string, string, table) or (nil, nil, table): | ||
72 | -- 1. latest installed version of the rock matching the dependency | ||
73 | -- 2. location where the installed version is installed | ||
74 | -- 3. the 'dep' query table | ||
75 | -- 4. true if provided via VM | ||
76 | -- or | ||
77 | -- 1. nil | ||
78 | -- 2. nil | ||
79 | -- 3. either 'dep' or an alternative query to be used | ||
80 | -- 4. false | ||
81 | local function match_dep(dep, get_versions) | ||
82 | assert(type(dep) == "table") | ||
83 | assert(type(get_versions) == "function") | ||
84 | |||
85 | local versions, locations, lockversion, provided = get_versions(dep) | ||
86 | |||
36 | local latest_version | 87 | local latest_version |
37 | local latest_vstring | 88 | local latest_vstring |
38 | for _, vstring in ipairs(versions) do | 89 | for _, vstring in ipairs(versions) do |
39 | if not blacklist or not blacklist[vstring] then | 90 | local version = vers.parse_version(vstring) |
40 | local version = vers.parse_version(vstring) | 91 | if vers.match_constraints(version, dep.constraints) then |
41 | if vers.match_constraints(version, dep.constraints) then | 92 | if not latest_version or version > latest_version then |
42 | if not latest_version or version > latest_version then | 93 | latest_version = version |
43 | latest_version = version | 94 | latest_vstring = vstring |
44 | latest_vstring = vstring | ||
45 | end | ||
46 | end | 95 | end |
47 | end | 96 | end |
48 | end | 97 | end |
49 | return latest_vstring, locations[latest_vstring] | 98 | |
99 | if lockversion and not locations[lockversion] then | ||
100 | local latest_matching_msg = "" | ||
101 | if latest_vstring and latest_vstring ~= lockversion then | ||
102 | latest_matching_msg = " (latest matching is " .. latest_vstring .. ")" | ||
103 | end | ||
104 | util.printout("Forcing " .. dep.name .. " to pinned version " .. lockversion .. latest_matching_msg) | ||
105 | return nil, nil, queries.new(dep.name, lockversion) | ||
106 | end | ||
107 | |||
108 | return latest_vstring, locations[latest_vstring], dep, provided | ||
50 | end | 109 | end |
51 | 110 | ||
52 | --- Attempt to match dependencies of a rockspec to installed rocks. | 111 | local function match_all_deps(dependencies, get_versions) |
53 | -- @param dependencies table: The table of dependencies. | 112 | assert(type(dependencies) == "table") |
54 | -- @param rocks_provided table: The table of auto-provided dependencies. | 113 | assert(type(get_versions) == "function") |
55 | -- @param blacklist table or nil: Program versions to not use as valid matches. | 114 | |
56 | -- Table where keys are program names and values are tables where keys | ||
57 | -- are program versions and values are 'true'. | ||
58 | -- @return table, table, table: A table where keys are dependencies parsed | ||
59 | -- in table format and values are tables containing fields 'name' and | ||
60 | -- version' representing matches; a table of missing dependencies | ||
61 | -- parsed as tables; and a table of "no-upgrade" missing dependencies | ||
62 | -- (to be used in plugin modules so that a plugin does not force upgrade of | ||
63 | -- its parent application). | ||
64 | function deps.match_deps(dependencies, rocks_provided, blacklist, deps_mode) | ||
65 | assert(type(blacklist) == "table" or not blacklist) | ||
66 | local matched, missing, no_upgrade = {}, {}, {} | 115 | local matched, missing, no_upgrade = {}, {}, {} |
67 | 116 | ||
68 | for _, dep in ipairs(dependencies) do | 117 | for _, dep in ipairs(dependencies) do |
69 | local found = match_dep(dep, blacklist and blacklist[dep.name] or nil, deps_mode, rocks_provided) | 118 | local found, _, provided |
119 | found, _, dep, provided = match_dep(dep, get_versions) | ||
70 | if found then | 120 | if found then |
71 | if not rocks_provided[dep.name] then | 121 | if not provided then |
72 | matched[dep] = {name = dep.name, version = found} | 122 | matched[dep] = {name = dep.name, version = found} |
73 | end | 123 | end |
74 | else | 124 | else |
@@ -82,20 +132,35 @@ function deps.match_deps(dependencies, rocks_provided, blacklist, deps_mode) | |||
82 | return matched, missing, no_upgrade | 132 | return matched, missing, no_upgrade |
83 | end | 133 | end |
84 | 134 | ||
85 | --- Return a set of values of a table. | 135 | --- Attempt to match dependencies of a rockspec to installed rocks. |
86 | -- @param tbl table: The input table. | 136 | -- @param dependencies table: The table of dependencies. |
87 | -- @return table: The array of keys. | 137 | -- @param rocks_provided table: The table of auto-provided dependencies. |
88 | local function values_set(tbl) | 138 | -- @param blacklist table or nil: Program versions to not use as valid matches. |
89 | local set = {} | 139 | -- Table where keys are program names and values are tables where keys |
90 | for _, v in pairs(tbl) do | 140 | -- are program versions and values are 'true'. |
91 | set[v] = true | 141 | -- @param deps_mode string: Which trees to check dependencies for |
92 | end | 142 | -- @return table, table, table: A table where keys are dependencies parsed |
93 | return set | 143 | -- in table format and values are tables containing fields 'name' and |
144 | -- version' representing matches; a table of missing dependencies | ||
145 | -- parsed as tables; and a table of "no-upgrade" missing dependencies | ||
146 | -- (to be used in plugin modules so that a plugin does not force upgrade of | ||
147 | -- its parent application). | ||
148 | function deps.match_deps(dependencies, rocks_provided, blacklist, deps_mode) | ||
149 | assert(type(dependencies) == "table") | ||
150 | assert(type(rocks_provided) == "table") | ||
151 | assert(type(blacklist) == "table" or blacklist == nil) | ||
152 | assert(type(deps_mode) == "string") | ||
153 | |||
154 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, "dependencies", blacklist) | ||
155 | return match_all_deps(dependencies, get_versions) | ||
94 | end | 156 | end |
95 | 157 | ||
96 | local function rock_status(name, deps_mode, rocks_provided) | 158 | local function rock_status(name, get_versions) |
97 | local installed = match_dep(queries.new(name), nil, deps_mode, rocks_provided) | 159 | assert(type(name) == "string") |
98 | local installation_type = rocks_provided[name] and "provided by VM" or "installed" | 160 | assert(type(get_versions) == "function") |
161 | |||
162 | local installed, _, _, provided = match_dep(queries.new(name), get_versions) | ||
163 | local installation_type = provided and "provided by VM" or "installed" | ||
99 | return installed and installed.." "..installation_type or "not installed" | 164 | return installed and installed.." "..installation_type or "not installed" |
100 | end | 165 | end |
101 | 166 | ||
@@ -103,7 +168,7 @@ end | |||
103 | -- @param name string: package name. | 168 | -- @param name string: package name. |
104 | -- @param version string: package version. | 169 | -- @param version string: package version. |
105 | -- @param dependencies table: array of dependencies. | 170 | -- @param dependencies table: array of dependencies. |
106 | -- @param deps_mode string: Which trees to check dependencies for: | 171 | -- @param deps_mode string: Which trees to check dependencies for |
107 | -- @param rocks_provided table: A table of auto-dependencies provided | 172 | -- @param rocks_provided table: A table of auto-dependencies provided |
108 | -- by this Lua implementation for the given dependency. | 173 | -- by this Lua implementation for the given dependency. |
109 | -- "one" for the current default tree, "all" for all trees, | 174 | -- "one" for the current default tree, "all" for all trees, |
@@ -114,58 +179,53 @@ function deps.report_missing_dependencies(name, version, dependencies, deps_mode | |||
114 | assert(type(dependencies) == "table") | 179 | assert(type(dependencies) == "table") |
115 | assert(type(deps_mode) == "string") | 180 | assert(type(deps_mode) == "string") |
116 | assert(type(rocks_provided) == "table") | 181 | assert(type(rocks_provided) == "table") |
182 | |||
183 | if deps_mode == "none" then | ||
184 | return | ||
185 | end | ||
186 | |||
187 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, "dependencies") | ||
117 | 188 | ||
118 | local first_missing_dep = true | 189 | local first_missing_dep = true |
119 | 190 | ||
120 | for _, dep in ipairs(dependencies) do | 191 | for _, dep in ipairs(dependencies) do |
121 | if not match_dep(dep, nil, deps_mode, rocks_provided) then | 192 | local found, _ |
193 | found, _, dep = match_dep(dep, get_versions) | ||
194 | if not found then | ||
122 | if first_missing_dep then | 195 | if first_missing_dep then |
123 | util.printout(("Missing dependencies for %s %s:"):format(name, version)) | 196 | util.printout(("Missing dependencies for %s %s:"):format(name, version)) |
124 | first_missing_dep = false | 197 | first_missing_dep = false |
125 | end | 198 | end |
126 | 199 | ||
127 | util.printout((" %s (%s)"):format(tostring(dep), rock_status(dep.name, deps_mode, rocks_provided))) | 200 | util.printout((" %s (%s)"):format(tostring(dep), rock_status(dep.name, get_versions))) |
128 | end | 201 | end |
129 | end | 202 | end |
130 | end | 203 | end |
131 | 204 | ||
132 | function deps.fulfill_dependency(dep, deps_mode, name, version, rocks_provided, verify) | 205 | function deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey) |
133 | assert(dep:type() == "query") | 206 | assert(dep:type() == "query") |
134 | assert(type(deps_mode) == "string" or deps_mode == nil) | 207 | assert(type(deps_mode) == "string" or deps_mode == nil) |
135 | assert(type(name) == "string" or name == nil) | ||
136 | assert(type(version) == "string" or version == nil) | ||
137 | assert(type(rocks_provided) == "table" or rocks_provided == nil) | 208 | assert(type(rocks_provided) == "table" or rocks_provided == nil) |
138 | assert(type(verify) == "boolean" or verify == nil) | 209 | assert(type(verify) == "boolean" or verify == nil) |
210 | assert(type(depskey) == "string") | ||
211 | |||
139 | deps_mode = deps_mode or "all" | 212 | deps_mode = deps_mode or "all" |
140 | rocks_provided = rocks_provided or {} | 213 | rocks_provided = rocks_provided or {} |
141 | 214 | ||
142 | local found, where = match_dep(dep, nil, deps_mode, rocks_provided) | 215 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, depskey) |
216 | |||
217 | local found, where | ||
218 | found, where, dep = match_dep(dep, get_versions) | ||
143 | if found then | 219 | if found then |
220 | local tree_manifests = manif.load_rocks_tree_manifests(deps_mode) | ||
221 | manif.scan_dependencies(dep.name, found, tree_manifests, deplocks.proxy(depskey)) | ||
144 | return true, found, where | 222 | return true, found, where |
145 | end | 223 | end |
146 | 224 | ||
147 | local search = require("luarocks.search") | 225 | local search = require("luarocks.search") |
148 | local install = require("luarocks.cmd.install") | 226 | local install = require("luarocks.cmd.install") |
149 | 227 | ||
150 | if name and version then | 228 | local url, search_err = search.find_suitable_rock(dep, true) |
151 | util.printout(("%s %s depends on %s (%s)"):format( | ||
152 | name, version, tostring(dep), rock_status(dep.name, deps_mode, rocks_provided))) | ||
153 | else | ||
154 | util.printout(("Fulfilling dependency on %s (%s)"):format( | ||
155 | tostring(dep), rock_status(dep.name, deps_mode, rocks_provided))) | ||
156 | end | ||
157 | |||
158 | if dep.constraints[1] and dep.constraints[1].no_upgrade then | ||
159 | util.printerr("This version of "..name.." is designed for use with") | ||
160 | util.printerr(tostring(dep)..", but is configured to avoid upgrading it") | ||
161 | util.printerr("automatically. Please upgrade "..dep.name.." with") | ||
162 | util.printerr(" luarocks install "..dep.name) | ||
163 | util.printerr("or choose an older version of "..name.." with") | ||
164 | util.printerr(" luarocks search "..name) | ||
165 | return nil, "Failed matching dependencies" | ||
166 | end | ||
167 | |||
168 | local url, search_err = search.find_suitable_rock(dep) | ||
169 | if not url then | 229 | if not url then |
170 | return nil, "Could not satisfy dependency "..tostring(dep)..": "..search_err | 230 | return nil, "Could not satisfy dependency "..tostring(dep)..": "..search_err |
171 | end | 231 | end |
@@ -181,27 +241,12 @@ function deps.fulfill_dependency(dep, deps_mode, name, version, rocks_provided, | |||
181 | return nil, "Failed installing dependency: "..url.." - "..install_err, errcode | 241 | return nil, "Failed installing dependency: "..url.." - "..install_err, errcode |
182 | end | 242 | end |
183 | 243 | ||
184 | found, where = match_dep(dep, nil, deps_mode, rocks_provided) | 244 | found, where = match_dep(dep, get_versions) |
185 | assert(found) | 245 | assert(found) |
186 | return true, found, where | 246 | return true, found, where |
187 | end | 247 | end |
188 | 248 | ||
189 | --- Check dependencies of a rock and attempt to install any missing ones. | 249 | local function check_supported_platforms(rockspec) |
190 | -- Packages are installed using the LuaRocks "install" command. | ||
191 | -- Aborts the program if a dependency could not be fulfilled. | ||
192 | -- @param rockspec table: A rockspec in table format. | ||
193 | -- @param depskey string: Rockspec key to fetch to get dependency table. | ||
194 | -- @param deps_mode string | ||
195 | -- @param verify boolean | ||
196 | -- @return boolean or (nil, string, [string]): True if no errors occurred, or | ||
197 | -- nil and an error message if any test failed, followed by an optional | ||
198 | -- error code. | ||
199 | function deps.fulfill_dependencies(rockspec, depskey, deps_mode, verify) | ||
200 | assert(type(rockspec) == "table") | ||
201 | assert(type(depskey) == "string") | ||
202 | assert(type(deps_mode) == "string") | ||
203 | assert(type(verify) == "boolean" or verify == nil) | ||
204 | |||
205 | if rockspec.supported_platforms and next(rockspec.supported_platforms) then | 250 | if rockspec.supported_platforms and next(rockspec.supported_platforms) then |
206 | local all_negative = true | 251 | local all_negative = true |
207 | local supported = false | 252 | local supported = false |
@@ -225,14 +270,82 @@ function deps.fulfill_dependencies(rockspec, depskey, deps_mode, verify) | |||
225 | return nil, "This rockspec for "..rockspec.package.." does not support "..plats.." platforms." | 270 | return nil, "This rockspec for "..rockspec.package.." does not support "..plats.." platforms." |
226 | end | 271 | end |
227 | end | 272 | end |
273 | |||
274 | return true | ||
275 | end | ||
228 | 276 | ||
229 | deps.report_missing_dependencies(rockspec.name, rockspec.version, rockspec[depskey], deps_mode, rockspec.rocks_provided) | 277 | --- Check dependencies of a rock and attempt to install any missing ones. |
278 | -- Packages are installed using the LuaRocks "install" command. | ||
279 | -- Aborts the program if a dependency could not be fulfilled. | ||
280 | -- @param rockspec table: A rockspec in table format. | ||
281 | -- @param depskey string: Rockspec key to fetch to get dependency table. | ||
282 | -- @param deps_mode string | ||
283 | -- @param verify boolean | ||
284 | -- @param deplock_dir string: dirname of the deplock file | ||
285 | -- @return boolean or (nil, string, [string]): True if no errors occurred, or | ||
286 | -- nil and an error message if any test failed, followed by an optional | ||
287 | -- error code. | ||
288 | function deps.fulfill_dependencies(rockspec, depskey, deps_mode, verify, deplock_dir) | ||
289 | assert(type(rockspec) == "table") | ||
290 | assert(type(depskey) == "string") | ||
291 | assert(type(deps_mode) == "string") | ||
292 | assert(type(verify) == "boolean" or verify == nil) | ||
293 | assert(type(deplock_dir) == "string" or deplock_dir == nil) | ||
294 | |||
295 | local name = rockspec.name | ||
296 | local version = rockspec.version | ||
297 | local rocks_provided = rockspec.rocks_provided | ||
298 | |||
299 | local ok, filename, err = deplocks.load(name, deplock_dir or ".") | ||
300 | if filename then | ||
301 | util.printout("Using dependencies pinned in lockfile: " .. filename) | ||
302 | |||
303 | local get_versions = prepare_get_versions("none", rocks_provided, depskey) | ||
304 | for dname, dversion in deplocks.each(depskey) do | ||
305 | local dep = queries.new(dname, dversion) | ||
306 | |||
307 | util.printout(("%s %s is pinned to %s (%s)"):format( | ||
308 | name, version, tostring(dep), rock_status(dep.name, get_versions))) | ||
309 | |||
310 | local ok, err = deps.fulfill_dependency(dep, "none", rocks_provided, verify, depskey) | ||
311 | if not ok then | ||
312 | return nil, err | ||
313 | end | ||
314 | end | ||
315 | util.printout() | ||
316 | return true | ||
317 | elseif err then | ||
318 | util.warning(err) | ||
319 | end | ||
320 | |||
321 | ok, err = check_supported_platforms(rockspec) | ||
322 | if not ok then | ||
323 | return nil, err | ||
324 | end | ||
325 | |||
326 | deps.report_missing_dependencies(name, version, rockspec[depskey], deps_mode, rocks_provided) | ||
230 | 327 | ||
231 | util.printout() | 328 | util.printout() |
329 | |||
330 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, depskey) | ||
232 | for _, dep in ipairs(rockspec[depskey]) do | 331 | for _, dep in ipairs(rockspec[depskey]) do |
233 | local ok, err = deps.fulfill_dependency(dep, deps_mode, rockspec.name, rockspec.version, rockspec.rocks_provided, verify) | 332 | |
234 | if not ok then | 333 | util.printout(("%s %s depends on %s (%s)"):format( |
235 | return nil, err | 334 | name, version, tostring(dep), rock_status(dep.name, get_versions))) |
335 | |||
336 | local ok, found_or_err, _, no_upgrade = deps.fulfill_dependency(dep, deps_mode, rocks_provided, verify, depskey) | ||
337 | if ok then | ||
338 | deplocks.add(depskey, dep.name, found_or_err) | ||
339 | else | ||
340 | if no_upgrade then | ||
341 | util.printerr("This version of "..name.." is designed for use with") | ||
342 | util.printerr(tostring(dep)..", but is configured to avoid upgrading it") | ||
343 | util.printerr("automatically. Please upgrade "..dep.name.." with") | ||
344 | util.printerr(" luarocks install "..dep.name) | ||
345 | util.printerr("or look for a suitable version of "..name.." with") | ||
346 | util.printerr(" luarocks search "..name) | ||
347 | end | ||
348 | return nil, found_or_err | ||
236 | end | 349 | end |
237 | end | 350 | end |
238 | 351 | ||
@@ -500,7 +613,10 @@ function deps.scan_deps(results, manifest, name, version, deps_mode) | |||
500 | else | 613 | else |
501 | rocks_provided = util.get_rocks_provided() | 614 | rocks_provided = util.get_rocks_provided() |
502 | end | 615 | end |
503 | local matched = deps.match_deps(dependencies, rocks_provided, nil, deps_mode) | 616 | |
617 | local get_versions = prepare_get_versions(deps_mode, rocks_provided, "dependencies") | ||
618 | |||
619 | local matched = match_all_deps(dependencies, get_versions) | ||
504 | results[name] = version | 620 | results[name] = version |
505 | for _, match in pairs(matched) do | 621 | for _, match in pairs(matched) do |
506 | deps.scan_deps(results, manifest, match.name, match.version, deps_mode) | 622 | deps.scan_deps(results, manifest, match.name, match.version, deps_mode) |
diff --git a/src/luarocks/persist.lua b/src/luarocks/persist.lua index 1c4b82b5..b21323ce 100644 --- a/src/luarocks/persist.lua +++ b/src/luarocks/persist.lua | |||
@@ -8,6 +8,7 @@ local util = require("luarocks.util") | |||
8 | local dir = require("luarocks.dir") | 8 | local dir = require("luarocks.dir") |
9 | local fs = require("luarocks.fs") | 9 | local fs = require("luarocks.fs") |
10 | 10 | ||
11 | persist.run_file = core.run_file | ||
11 | persist.load_into_table = core.load_into_table | 12 | persist.load_into_table = core.load_into_table |
12 | 13 | ||
13 | local write_table | 14 | local write_table |
@@ -200,7 +201,7 @@ function persist.save_from_table(filename, tbl, field_order) | |||
200 | end | 201 | end |
201 | 202 | ||
202 | --- Save the contents of a table as a module. | 203 | --- Save the contents of a table as a module. |
203 | -- Each element of the table is saved as a global assignment. | 204 | -- The module contains a 'return' statement that returns the table. |
204 | -- Only numbers, strings and tables (containing numbers, strings | 205 | -- Only numbers, strings and tables (containing numbers, strings |
205 | -- or other recursively processed tables) are supported. | 206 | -- or other recursively processed tables) are supported. |
206 | -- @param filename string: the output filename | 207 | -- @param filename string: the output filename |
diff --git a/src/luarocks/test/busted.lua b/src/luarocks/test/busted.lua index 618054c7..8fa78804 100644 --- a/src/luarocks/test/busted.lua +++ b/src/luarocks/test/busted.lua | |||
@@ -21,7 +21,7 @@ function busted.run_tests(test, args) | |||
21 | test = {} | 21 | test = {} |
22 | end | 22 | end |
23 | 23 | ||
24 | local ok, bustedver, where = deps.fulfill_dependency(queries.new("busted")) | 24 | local ok, bustedver, where = deps.fulfill_dependency(queries.new("busted"), nil, nil, nil, "test_dependencies") |
25 | if not ok then | 25 | if not ok then |
26 | return nil, bustedver | 26 | return nil, bustedver |
27 | end | 27 | end |