summaryrefslogtreecommitdiff
path: root/src/luarocks/rockspecs.lua
diff options
context:
space:
mode:
authorMike Vink <mike@pionative.com>2025-02-03 21:29:42 +0100
committerMike Vink <mike@pionative.com>2025-02-03 21:29:42 +0100
commit5155816b7b925dec5d5feb1568b1d7ceb00938b9 (patch)
treedeca28ea15e79f6f804c3d90d2ba757881638af5 /src/luarocks/rockspecs.lua
fetch tarballHEADmaster
Diffstat (limited to 'src/luarocks/rockspecs.lua')
-rw-r--r--src/luarocks/rockspecs.lua183
1 files changed, 183 insertions, 0 deletions
diff --git a/src/luarocks/rockspecs.lua b/src/luarocks/rockspecs.lua
new file mode 100644
index 0000000..454bab7
--- /dev/null
+++ b/src/luarocks/rockspecs.lua
@@ -0,0 +1,183 @@
+local rockspecs = {}
+
+local cfg = require("luarocks.core.cfg")
+local dir = require("luarocks.dir")
+local path = require("luarocks.path")
+local queries = require("luarocks.queries")
+local type_rockspec = require("luarocks.type.rockspec")
+local util = require("luarocks.util")
+local vers = require("luarocks.core.vers")
+
+local vendored_build_type_set = {
+ ["builtin"] = true,
+ ["cmake"] = true,
+ ["command"] = true,
+ ["make"] = true,
+ ["module"] = true, -- compatibility alias
+ ["none"] = true,
+}
+
+local rockspec_mt = {}
+
+rockspec_mt.__index = rockspec_mt
+
+function rockspec_mt.type()
+ return "rockspec"
+end
+
+--- Perform platform-specific overrides on a table.
+-- Overrides values of table with the contents of the appropriate
+-- subset of its "platforms" field. The "platforms" field should
+-- be a table containing subtables keyed with strings representing
+-- platform names. Names that match the contents of the global
+-- detected platforms setting are used. For example, if
+-- platform "unix" is detected, then the fields of
+-- tbl.platforms.unix will overwrite those of tbl with the same
+-- names. For table values, the operation is performed recursively
+-- (tbl.platforms.foo.x.y.z overrides tbl.x.y.z; other contents of
+-- tbl.x are preserved).
+-- @param tbl table or nil: Table which may contain a "platforms" field;
+-- if it doesn't (or if nil is passed), this function does nothing.
+local function platform_overrides(tbl)
+ assert(type(tbl) == "table" or not tbl)
+
+ if not tbl then return end
+
+ if tbl.platforms then
+ for platform in cfg.each_platform() do
+ local platform_tbl = tbl.platforms[platform]
+ if platform_tbl then
+ util.deep_merge(tbl, platform_tbl)
+ end
+ end
+ end
+ tbl.platforms = nil
+end
+
+local function convert_dependencies(rockspec, key)
+ if rockspec[key] then
+ for i = 1, #rockspec[key] do
+ local parsed, err = queries.from_dep_string(rockspec[key][i])
+ if not parsed then
+ return nil, "Parse error processing dependency '"..rockspec[key][i].."': "..tostring(err)
+ end
+ rockspec[key][i] = parsed
+ end
+ else
+ rockspec[key] = {}
+ end
+ return true
+end
+
+--- Set up path-related variables for a given rock.
+-- Create a "variables" table in the rockspec table, containing
+-- adjusted variables according to the configuration file.
+-- @param rockspec table: The rockspec table.
+local function configure_paths(rockspec)
+ local vars = {}
+ for k,v in pairs(cfg.variables) do
+ vars[k] = v
+ end
+ local name, version = rockspec.name, rockspec.version
+ vars.PREFIX = path.install_dir(name, version)
+ vars.LUADIR = path.lua_dir(name, version)
+ vars.LIBDIR = path.lib_dir(name, version)
+ vars.CONFDIR = path.conf_dir(name, version)
+ vars.BINDIR = path.bin_dir(name, version)
+ vars.DOCDIR = path.doc_dir(name, version)
+ rockspec.variables = vars
+end
+
+function rockspecs.from_persisted_table(filename, rockspec, globals, quick)
+ assert(type(rockspec) == "table")
+ assert(type(globals) == "table" or globals == nil)
+ assert(type(filename) == "string")
+ assert(type(quick) == "boolean" or quick == nil)
+
+ if rockspec.rockspec_format then
+ if vers.compare_versions(rockspec.rockspec_format, type_rockspec.rockspec_format) then
+ return nil, "Rockspec format "..rockspec.rockspec_format.." is not supported, please upgrade LuaRocks."
+ end
+ end
+
+ if not quick then
+ local ok, err = type_rockspec.check(rockspec, globals or {})
+ if not ok then
+ return nil, err
+ end
+ end
+
+ --- Check if rockspec format version satisfies version requirement.
+ -- @param rockspec table: The rockspec table.
+ -- @param version string: required version.
+ -- @return boolean: true if rockspec format matches version or is newer, false otherwise.
+ do
+ local parsed_format = vers.parse_version(rockspec.rockspec_format or "1.0")
+ rockspec.format_is_at_least = function(self, version)
+ return parsed_format >= vers.parse_version(version)
+ end
+ end
+
+ platform_overrides(rockspec.build)
+ platform_overrides(rockspec.dependencies)
+ platform_overrides(rockspec.build_dependencies)
+ platform_overrides(rockspec.test_dependencies)
+ platform_overrides(rockspec.external_dependencies)
+ platform_overrides(rockspec.source)
+ platform_overrides(rockspec.hooks)
+ platform_overrides(rockspec.test)
+
+ rockspec.name = rockspec.package:lower()
+
+ local protocol, pathname = dir.split_url(rockspec.source.url)
+ if dir.is_basic_protocol(protocol) then
+ rockspec.source.file = rockspec.source.file or dir.base_name(rockspec.source.url)
+ end
+ rockspec.source.protocol, rockspec.source.pathname = protocol, pathname
+
+ -- Temporary compatibility
+ if rockspec.source.cvs_module then rockspec.source.module = rockspec.source.cvs_module end
+ if rockspec.source.cvs_tag then rockspec.source.tag = rockspec.source.cvs_tag end
+
+ rockspec.local_abs_filename = filename
+ rockspec.source.dir_set = rockspec.source.dir ~= nil
+ rockspec.source.dir = rockspec.source.dir or rockspec.source.module
+
+ rockspec.rocks_provided = util.get_rocks_provided(rockspec)
+
+ for _, key in ipairs({"dependencies", "build_dependencies", "test_dependencies"}) do
+ local ok, err = convert_dependencies(rockspec, key)
+ if not ok then
+ return nil, err
+ end
+ end
+
+ if rockspec.build
+ and rockspec.build.type
+ and not vendored_build_type_set[rockspec.build.type] then
+ local build_pkg_name = "luarocks-build-" .. rockspec.build.type
+ if not rockspec.build_dependencies then
+ rockspec.build_dependencies = {}
+ end
+
+ local found = false
+ for _, dep in ipairs(rockspec.build_dependencies) do
+ if dep.name == build_pkg_name then
+ found = true
+ break
+ end
+ end
+
+ if not found then
+ table.insert(rockspec.build_dependencies, queries.from_dep_string(build_pkg_name))
+ end
+ end
+
+ if not quick then
+ configure_paths(rockspec)
+ end
+
+ return setmetatable(rockspec, rockspec_mt)
+end
+
+return rockspecs