From acf8bcb82ae697a5bac94bfbe93c3ad9d7487795 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Fri, 8 Nov 2019 18:19:17 -0300 Subject: 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. --- spec/build_spec.lua | 41 +++++++++- spec/doc_spec.lua | 2 +- spec/fixtures/a_repo/a_rock-2.0-1.src.rock | Bin 0 -> 541 bytes spec/fixtures/a_repo/manifest | 5 ++ spec/fixtures/a_repo/manifest-5.1 | 5 ++ spec/fixtures/a_repo/manifest-5.1.zip | Bin 350 -> 358 bytes spec/fixtures/a_repo/manifest-5.2 | 5 ++ spec/fixtures/a_repo/manifest-5.2.zip | Bin 350 -> 358 bytes spec/fixtures/a_repo/manifest-5.3 | 5 ++ spec/fixtures/a_repo/manifest-5.3.zip | Bin 350 -> 358 bytes spec/install_spec.lua | 44 +++++++++++ spec/make_spec.lua | 119 +++++++++++++++++++++++++++++ 12 files changed, 222 insertions(+), 4 deletions(-) create mode 100644 spec/fixtures/a_repo/a_rock-2.0-1.src.rock (limited to 'spec') 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() end) it("with --only-sources", function() - assert.is_true(run.luarocks_bool("download --server=" .. testing_paths.fixtures_dir .. "/a_repo --rockspec a_rock")) + assert.is_true(run.luarocks_bool("download --server=" .. testing_paths.fixtures_dir .. "/a_repo --rockspec a_rock 1.0")) assert.is_false(run.luarocks_bool("build --only-sources=\"http://example.com\" a_rock-1.0-1.rockspec")) assert.is.falsy(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) - assert.is_true(run.luarocks_bool("download --server=" .. testing_paths.fixtures_dir .. "/a_repo --source a_rock")) + assert.is_true(run.luarocks_bool("download --server=" .. testing_paths.fixtures_dir .. "/a_repo --source a_rock 1.0")) assert.is_true(run.luarocks_bool("build --only-sources=\"http://example.com\" a_rock-1.0-1.src.rock")) assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/a_rock/1.0-1/a_rock-1.0-1.rockspec")) @@ -199,7 +199,42 @@ describe("LuaRocks build #integration", function() assert.is.truthy(lfs.attributes(testing_paths.testing_sys_rocks .. "/test/1.0-1/test-1.0-1.rockspec")) end) end) - + + it("supports --pin #pinning", function() + test_env.run_in_tmp(function(tmpdir) + write_file("test-1.0-1.rockspec", [[ + package = "test" + version = "1.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" + } + dependencies = { + "a_rock >= 0.8" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]], finally) + write_file("test.lua", "return {}", finally) + + assert.is_true(run.luarocks_bool("build --server=" .. testing_paths.fixtures_dir .. "/a_repo test-1.0-1.rockspec --pin --tree=lua_modules")) + assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/test-1.0-1.rockspec")) + 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")) + local lockfilename = "./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/luarocks.lock" + assert.is.truthy(lfs.attributes(lockfilename)) + local lockdata = loadfile(lockfilename)() + assert.same({ + dependencies = { + ["a_rock"] = "2.0-1", + ["lua"] = test_env.lua_version .. "-1", + } + }, lockdata) + end) + end) + it("lmathx deps partial match", function() assert.is_true(run.luarocks_bool("build lmathx")) 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() describe("#namespaces", function() it("retrieves docs for a namespaced package from the command-line", function() assert(run.luarocks_bool("build a_user/a_rock --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) - assert(run.luarocks_bool("build a_rock --keep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) + assert(run.luarocks_bool("build a_rock 1.0 --keep --server=" .. testing_paths.fixtures_dir .. "/a_repo" )) assert.match("a_rock 2.0", run.luarocks("doc a_user/a_rock")) end) 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 Binary files /dev/null and b/spec/fixtures/a_repo/a_rock-2.0-1.src.rock 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 = { { arch = "rockspec" } + }, + ["2.0-1"] = { + { + arch = "src" + } } }, 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 = { { arch = "rockspec" } + }, + ["2.0-1"] = { + { + arch = "src" + } } }, 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 Binary files a/spec/fixtures/a_repo/manifest-5.1.zip and b/spec/fixtures/a_repo/manifest-5.1.zip 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 = { { arch = "rockspec" } + }, + ["2.0-1"] = { + { + arch = "src" + } } }, 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 Binary files a/spec/fixtures/a_repo/manifest-5.2.zip and b/spec/fixtures/a_repo/manifest-5.2.zip 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 = { { arch = "rockspec" } + }, + ["2.0-1"] = { + { + arch = "src" + } } }, 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 Binary files a/spec/fixtures/a_repo/manifest-5.3.zip and b/spec/fixtures/a_repo/manifest-5.3.zip 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() end) end) + it("respects luarocks.lock in package #pinning", function() + test_env.run_in_tmp(function(tmpdir) + write_file("test-1.0-1.rockspec", [[ + package = "test" + version = "1.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" + } + dependencies = { + "a_rock >= 0.8" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]], finally) + write_file("test.lua", "return {}", finally) + write_file("luarocks.lock", [[ + return { + dependencies = { + ["a_rock"] = "1.0-1", + } + } + ]], finally) + + assert.is_true(run.luarocks_bool("make --pack-binary-rock --server=" .. testing_paths.fixtures_dir .. "/a_repo test-1.0-1.rockspec")) + assert.is_true(os.remove("luarocks.lock")) + + assert.is.truthy(lfs.attributes("./test-1.0-1.all.rock")) + + assert.is.falsy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/test-1.0-1.rockspec")) + 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")) + + print(run.luarocks("install ./test-1.0-1.all.rock --tree=lua_modules --server=" .. testing_paths.fixtures_dir .. "/a_repo")) + + assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/test-1.0-1.rockspec")) + assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/luarocks.lock")) + 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")) + assert.is.falsy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/a_rock/2.0-1")) + end) + end) + describe("#unix install runs build from #git", function() local git 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") local run = test_env.run local testing_paths = test_env.testing_paths local env_variables = test_env.env_variables +local write_file = test_env.write_file test_env.unload_luarocks() @@ -125,6 +126,124 @@ describe("LuaRocks make tests #integration", function() end) end) + it("supports --pin #pinning", function() + test_env.run_in_tmp(function(tmpdir) + write_file("test-1.0-1.rockspec", [[ + package = "test" + version = "1.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" + } + dependencies = { + "a_rock 1.0" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]], finally) + write_file("test.lua", "return {}", finally) + + assert.is_true(run.luarocks_bool("make --server=" .. testing_paths.fixtures_dir .. "/a_repo --pin --tree=lua_modules")) + assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/test-1.0-1.rockspec")) + 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")) + local lockfilename = "./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/1.0-1/luarocks.lock" + assert.is.truthy(lfs.attributes(lockfilename)) + local lockdata = loadfile(lockfilename)() + assert.same({ + dependencies = { + ["a_rock"] = "1.0-1", + ["lua"] = test_env.lua_version .. "-1", + } + }, lockdata) + end) + end) + + it("respects luarocks.lock when present #pinning", function() + test_env.run_in_tmp(function(tmpdir) + write_file("test-2.0-1.rockspec", [[ + package = "test" + version = "2.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" + } + dependencies = { + "a_rock >= 0.8" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]], finally) + write_file("test.lua", "return {}", finally) + write_file("luarocks.lock", [[ + return { + dependencies = { + ["a_rock"] = "1.0-1", + } + } + ]], finally) + + print(run.luarocks("make --server=" .. testing_paths.fixtures_dir .. "/a_repo --tree=lua_modules")) + assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/2.0-1/test-2.0-1.rockspec")) + 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")) + local lockfilename = "./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/2.0-1/luarocks.lock" + assert.is.truthy(lfs.attributes(lockfilename)) + local lockdata = loadfile(lockfilename)() + assert.same({ + dependencies = { + ["a_rock"] = "1.0-1", + } + }, lockdata) + end) + end) + + it("overrides luarocks.lock with --pin #pinning", function() + test_env.run_in_tmp(function(tmpdir) + write_file("test-2.0-1.rockspec", [[ + package = "test" + version = "2.0-1" + source = { + url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/test.lua" + } + dependencies = { + "a_rock >= 0.8" + } + build = { + type = "builtin", + modules = { + test = "test.lua" + } + } + ]], finally) + write_file("test.lua", "return {}", finally) + write_file("luarocks.lock", [[ + return { + dependencies = { + ["a_rock"] = "1.0-1", + } + } + ]], finally) + + print(run.luarocks("make --server=" .. testing_paths.fixtures_dir .. "/a_repo --tree=lua_modules --pin")) + assert.is.truthy(lfs.attributes("./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/2.0-1/test-2.0-1.rockspec")) + 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")) + local lockfilename = "./lua_modules/lib/luarocks/rocks-" .. test_env.lua_version .. "/test/2.0-1/luarocks.lock" + assert.is.truthy(lfs.attributes(lockfilename)) + local lockdata = loadfile(lockfilename)() + assert.same({ + dependencies = { + ["a_rock"] = "2.0-1", + ["lua"] = test_env.lua_version .. "-1", + } + }, lockdata) + end) + end) + describe("#ddt LuaRocks make upgrading rockspecs with double deploy types", function() local deploy_lib_dir = testing_paths.testing_sys_tree .. "/lib/lua/"..env_variables.LUA_VERSION local deploy_lua_dir = testing_paths.testing_sys_tree .. "/share/lua/"..env_variables.LUA_VERSION -- cgit v1.2.3-55-g6feb