From bec4a9cbf72c8e392163f50f7b6bbb18763d9f90 Mon Sep 17 00:00:00 2001 From: Hisham Muhammad Date: Mon, 6 Jun 2022 15:28:14 -0300 Subject: loader.which: new option for searching package.path and cpath Adds a new second argument, `where`, a string which indicates places to search for the module. If `where` contains "l", it will search using the LuaRocks loader; if it contains "p", it will look in the filesystem using package.path and package.cpath. You can use both at the same time. If successful, it will return four values. * If found using the LuaRocks loader, it will return: * filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so"), * rock name * rock version * "l" to indicate the match comes from the loader. * If found scanning package.path and package.cpath, it will return: * filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so"), * "path" or "cpath" * nil * "p" to indicate the match comes from scanning package.path and cpath. If unsuccessful, nothing is returned. --- spec/loader_spec.lua | 25 ++++++++++++++++++------- src/luarocks/cmd/which.lua | 22 +++++++--------------- src/luarocks/loader.lua | 46 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 66 insertions(+), 27 deletions(-) diff --git a/spec/loader_spec.lua b/spec/loader_spec.lua index 35179080..c8526117 100644 --- a/spec/loader_spec.lua +++ b/spec/loader_spec.lua @@ -4,10 +4,21 @@ local testing_paths = test_env.testing_paths local write_file = test_env.write_file describe("luarocks.loader", function() + + before_each(function() + test_env.setup_specs() + end) + describe("#unit", function() it("starts", function() assert(run.lua_bool([[-e "require 'luarocks.loader'; print(package.loaded['luarocks.loaded'])"]])) end) + + describe("which", function() + it("finds modules using package.path", function() + assert(run.lua_bool([[-e "loader = require 'luarocks.loader'; local x,y,z,p = loader.which('luarocks.loader', 'p'); assert(p == 'p')"]])) + end) + end) end) describe("#integration", function() @@ -21,13 +32,13 @@ describe("luarocks.loader", function() url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/rock_b_01.lua" } build = { - type = "builtin", + type = "builtin", modules = { rock_b = "rock_b_01.lua" } } ]], finally) - + write_file("rock_b_10.lua", "print('ROCK B 1.0'); return {}", finally) write_file("rock_b-1.0-1.rockspec", [[ package = "rock_b" @@ -36,13 +47,13 @@ describe("luarocks.loader", function() url = "file://]] .. tmpdir:gsub("\\", "/") .. [[/rock_b_10.lua" } build = { - type = "builtin", + type = "builtin", modules = { rock_b = "rock_b_10.lua" } } ]], finally) - + write_file("rock_a.lua", "require('rock_b'); return {}", finally) write_file("rock_a-2.0-1.rockspec", [[ package = "rock_a" @@ -54,7 +65,7 @@ describe("luarocks.loader", function() "rock_b < 1.0", } build = { - type = "builtin", + type = "builtin", modules = { rock_a = "rock_a.lua" } @@ -64,9 +75,9 @@ describe("luarocks.loader", function() print(run.luarocks("make --server=" .. testing_paths.fixtures_dir .. "/a_repo --tree=" .. testing_paths.testing_tree .. " ./rock_b-0.1-1.rockspec")) print(run.luarocks("make --server=" .. testing_paths.fixtures_dir .. "/a_repo --tree=" .. testing_paths.testing_tree .. " ./rock_b-1.0-1.rockspec --keep")) print(run.luarocks("make --server=" .. testing_paths.fixtures_dir .. "/a_repo --tree=" .. testing_paths.testing_tree .. " ./rock_a-2.0-1.rockspec")) - + local output = run.lua([[-e "require 'luarocks.loader'; require('rock_a')"]]) - + assert.matches("ROCK B 0.1", output, 1, true) end) end) diff --git a/src/luarocks/cmd/which.lua b/src/luarocks/cmd/which.lua index 7503df00..f50a43c3 100644 --- a/src/luarocks/cmd/which.lua +++ b/src/luarocks/cmd/which.lua @@ -6,7 +6,6 @@ local which_cmd = {} local loader = require("luarocks.loader") local cfg = require("luarocks.core.cfg") local util = require("luarocks.util") -local fs = require("luarocks.fs") function which_cmd.add_to_parser(parser) local cmd = parser:command("which", 'Given a module name like "foo.bar", '.. @@ -21,24 +20,17 @@ end --- Driver function for "which" command. -- @return boolean This function terminates the interpreter. function which_cmd.command(args) - local pathname, rock_name, rock_version = loader.which(args.modname) + local pathname, rock_name, rock_version, where = loader.which(args.modname, "lp") if pathname then util.printout(pathname) - util.printout("(provided by " .. tostring(rock_name) .. " " .. tostring(rock_version) .. ")") - return true - end - - local modpath = args.modname:gsub("%.", "/") - for _, v in ipairs({"path", "cpath"}) do - for p in package[v]:gmatch("([^;]+)") do - local pathname = p:gsub("%?", modpath) -- luacheck: ignore 421 - if fs.exists(pathname) then - util.printout(pathname) - util.printout("(found directly via package." .. v .. " -- not installed as a rock?)") - return true - end + if where == "l" then + util.printout("(provided by " .. tostring(rock_name) .. " " .. tostring(rock_version) .. ")") + else + local key = rock_name + util.printout("(found directly via package." .. key.. " -- not installed as a rock?)") end + return true end return nil, "Module '" .. args.modname .. "' not found." diff --git a/src/luarocks/loader.lua b/src/luarocks/loader.lua index 825e4ce7..772fdfcb 100644 --- a/src/luarocks/loader.lua +++ b/src/luarocks/loader.lua @@ -194,11 +194,47 @@ end --- Return the pathname of the file that would be loaded for a module. -- @param module string: module name (eg. "socket.core") --- @return filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so"), --- the rock name and the rock version. -function loader.which(module) - local rock_name, rock_version, file_name = select_module(module, path.which_i) - return file_name, rock_name, rock_version +-- @param where string: places to look for the module. If `where` contains +-- "l", it will search using the LuaRocks loader; if it contains "p", +-- it will look in the filesystem using package.path and package.cpath. +-- You can use both at the same time. +-- @return If successful, it will return four values. +-- * If found using the LuaRocks loader, it will return: +-- * filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so"), +-- * rock name +-- * rock version +-- * "l" to indicate the match comes from the loader. +-- * If found scanning package.path and package.cpath, it will return: +-- * filename of the module (eg. "/usr/local/lib/lua/5.1/socket/core.so"), +-- * "path" or "cpath" +-- * nil +-- * "p" to indicate the match comes from scanning package.path and cpath. +-- If unsuccessful, nothing is returned. +function loader.which(module, where) + where = where or "l" + if where:match("l") then + local rock_name, rock_version, file_name = select_module(module, path.which_i) + if rock_name then + local fd = io.open(file_name) + if fd then + fd:close() + return file_name, rock_name, rock_version, "l" + end + end + end + if where:match("p") then + local modpath = module:gsub("%.", "/") + for _, v in ipairs({"path", "cpath"}) do + for p in package[v]:gmatch("([^;]+)") do + local file_name = p:gsub("%?", modpath) -- luacheck: ignore 421 + local fd = io.open(file_name) + if fd then + fd:close() + return file_name, v, nil, "p" + end + end + end + end end --- Package loader for LuaRocks support. -- cgit v1.2.3-55-g6feb