Skip to content

Commit

Permalink
loaders: add require_first function (internal)
Browse files Browse the repository at this point in the history
Usage example:

```lua
local loaders = require('internal.loaders')
local vshard = loaders.require_first('vshard-ee', 'vshard')
```

The function is for internal use.

It would be nice to have something of this kind in the public API, but
I'm not going to solve it within this patch.

Needed for tarantool/tarantool-ee#815

NO_DOC=no public API changes
NO_CHANGELOG=see NO_DOC
  • Loading branch information
Totktonada committed Jun 18, 2024
1 parent 6d5f1db commit 3abd4f9
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/lua/loaders.lua
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,31 @@ _G.require = function(modname)
return raw_require(modname)
end

-- Load first available module from the given ones.
--
-- It just calls `require()` on the provided arguments (in the
-- given order) and once this call succeeds, the function returns
-- its result.
--
-- If neither of the given modules can be `require`'d, an error is
-- raised.
local function require_first(...)
if select('#', ...) == 0 then
error('loaders.require_first expects at least one argument', 0)
end

for i = 1, select('#', ...) do
local module_name = select(i, ...)
local ok, res = pcall(require, module_name)
if ok then
return res
end
end

local modules_str = ('"%s"'):format(table.concat({...}, '", "'))
error(('neither of modules %s are found'):format(modules_str), 0)
end

return {
ROCKS_LIB_PATH = ROCKS_LIB_PATH,
ROCKS_LUA_PATH = ROCKS_LUA_PATH,
Expand All @@ -545,4 +570,5 @@ return {
--
-- Usage: loaders.no_package_loaded[modname] = true
no_package_loaded = no_package_loaded,
require_first = require_first,
}
49 changes: 49 additions & 0 deletions test/app-luatest/require_first_test.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
local t = require('luatest')
local treegen = require('test.treegen')
local justrun = require('test.justrun')

local g = t.group()

g.before_all(treegen.init)
g.after_all(treegen.clean)

-- A few test cases for the loaders.require_first() function.
--
-- Note: The loaders module is internal.
g.test_basic = function(g)
local dir = treegen.prepare_directory(g, {}, {})
treegen.write_script(dir, 'a.lua', 'return {whoami = "a"}')
treegen.write_script(dir, 'b.lua', 'return {whoami = "b"}')

treegen.write_script(dir, 'main.lua', string.dump(function()
local loaders = require('internal.loaders')
local t = require('luatest')

for i, case in ipairs({
-- Positive test cases.
{args = {'a', 'b'}, exp = {whoami = 'a'}},
{args = {'b', 'a'}, exp = {whoami = 'b'}},
{args = {'a', 'c'}, exp = {whoami = 'a'}},
{args = {'c', 'a'}, exp = {whoami = 'a'}},
-- Negative test cases.
{args = {}, err = 'loaders.require_first expects at least one ' ..
'argument'},
{args = {'c'}, err = 'neither of modules "c" are found'},
{args = {'c', 'd'}, err = 'neither of modules "c", "d" are found'},
}) do
if case.exp ~= nil then
assert(case.err == nil)
local res = loaders.require_first(unpack(case.args))
t.assert_equals(res, case.exp, ('case #%03d'):format(i))
else
assert(case.err ~= nil)
t.assert_error_msg_equals(case.err, loaders.require_first,
unpack(case.args))
end
end
end))

local opts = {nojson = true, stderr = true}
local res = justrun.tarantool(dir, {}, {'main.lua'}, opts)
t.assert_equals(res.exit_code, 0, {res.stdout, res.stderr})
end

0 comments on commit 3abd4f9

Please sign in to comment.