From e8fffcffbb06ad2a77771af5e452645937675066 Mon Sep 17 00:00:00 2001 From: V1K1NGbg Date: Tue, 30 Jul 2024 20:53:21 +0300 Subject: added manifest and rockspec tl files --- src/luarocks/type/manifest.tl | 80 +++++++++++++++ src/luarocks/type/rockspec.tl | 221 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 301 insertions(+) create mode 100644 src/luarocks/type/manifest.tl create mode 100644 src/luarocks/type/rockspec.tl (limited to 'src') diff --git a/src/luarocks/type/manifest.tl b/src/luarocks/type/manifest.tl new file mode 100644 index 00000000..043366ea --- /dev/null +++ b/src/luarocks/type/manifest.tl @@ -0,0 +1,80 @@ +local type_manifest = {} + +local type_check = require("luarocks.type_check") + +local manifest_formats = type_check.declare_schemas({ + ["3.0"] = { + repository = { + _mandatory = true, + -- packages + _any = { + -- versions + _any = { + -- items + _any = { + arch = { _type = "string", _mandatory = true }, + modules = { _any = { _type = "string" } }, + commands = { _any = { _type = "string" } }, + dependencies = { _any = { _type = "string" } }, + -- TODO: to be extended with more metadata. + } + } + } + }, + modules = { + _mandatory = true, + -- modules + _any = { + -- providers + _any = { _type = "string" } + } + }, + commands = { + _mandatory = true, + -- modules + _any = { + -- commands + _any = { _type = "string" } + } + }, + dependencies = { + -- each module + _any = { + -- each version + _any = { + -- each dependency + _any = { + name = { _type = "string" }, + namespace = { _type = "string" }, + constraints = { + _any = { + no_upgrade = { _type = "boolean" }, + op = { _type = "string" }, + version = { + string = { _type = "string" }, + _any = { _type = "number" }, + } + } + } + } + } + } + } + } +}) + +--- Type check a manifest table. +-- Verify the correctness of elements from a +-- manifest table, reporting on unknown fields and type +-- mismatches. +-- @return boolean or (nil, string): true if type checking +-- succeeded, or nil and an error message if it failed. +function type_manifest.check(manifest, globals) + assert(type(manifest) == "table") + local format = manifest_formats["3.0"] + local ok, err = type_check.check_undeclared_globals(globals, format) + if not ok then return nil, err end + return type_check.type_check_table("3.0", manifest, format, "") +end + +return type_manifest diff --git a/src/luarocks/type/rockspec.tl b/src/luarocks/type/rockspec.tl new file mode 100644 index 00000000..0b3cf31f --- /dev/null +++ b/src/luarocks/type/rockspec.tl @@ -0,0 +1,221 @@ +local type_rockspec = {} + +local type_check = require("luarocks.type_check") + +type_rockspec.rockspec_format = "3.0" + +-- Syntax for type-checking tables: +-- +-- A type-checking table describes typing data for a value. +-- Any key starting with an underscore has a special meaning: +-- _type (string) is the Lua type of the value. Default is "table". +-- _mandatory (boolean) indicates if the value is a mandatory key in its container table. Default is false. +-- For "string" types only: +-- _pattern (string) is the string-matching pattern, valid for string types only. Default is ".*". +-- For "table" types only: +-- _any (table) is the type-checking table for unspecified keys, recursively checked. +-- _more (boolean) indicates that the table accepts unspecified keys and does not type-check them. +-- Any other string keys that don't start with an underscore represent known keys and are type-checking tables, recursively checked. + +local rockspec_formats, versions = type_check.declare_schemas({ + ["1.0"] = { + rockspec_format = { _type = "string" }, + package = { _type = "string", _mandatory = true }, + version = { _type = "string", _pattern = "[%w.]+-[%d]+", _mandatory = true }, + description = { + summary = { _type = "string" }, + detailed = { _type = "string" }, + homepage = { _type = "string" }, + license = { _type = "string" }, + maintainer = { _type = "string" }, + }, + dependencies = { + platforms = type_check.MAGIC_PLATFORMS, + _any = { + _type = "string", + _name = "a valid dependency string", + _pattern = "%s*([a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*([^/]*)", + }, + }, + supported_platforms = { + _any = { _type = "string" }, + }, + external_dependencies = { + platforms = type_check.MAGIC_PLATFORMS, + _any = { + program = { _type = "string" }, + header = { _type = "string" }, + library = { _type = "string" }, + } + }, + source = { + _mandatory = true, + platforms = type_check.MAGIC_PLATFORMS, + url = { _type = "string", _mandatory = true }, + md5 = { _type = "string" }, + file = { _type = "string" }, + dir = { _type = "string" }, + tag = { _type = "string" }, + branch = { _type = "string" }, + module = { _type = "string" }, + cvs_tag = { _type = "string" }, + cvs_module = { _type = "string" }, + }, + build = { + platforms = type_check.MAGIC_PLATFORMS, + type = { _type = "string" }, + install = { + lua = { + _more = true + }, + lib = { + _more = true + }, + conf = { + _more = true + }, + bin = { + _more = true + } + }, + copy_directories = { + _any = { _type = "string" }, + }, + _more = true, + _mandatory = true + }, + hooks = { + platforms = type_check.MAGIC_PLATFORMS, + post_install = { _type = "string" }, + }, + }, + + ["1.1"] = { + deploy = { + wrap_bin_scripts = { _type = "boolean" }, + } + }, + + ["3.0"] = { + description = { + labels = { + _any = { _type = "string" } + }, + issues_url = { _type = "string" }, + }, + dependencies = { + _any = { + _pattern = "%s*([a-zA-Z0-9%.%-%_]*/?[a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*([^/]*)", + }, + }, + build_dependencies = { + platforms = type_check.MAGIC_PLATFORMS, + _any = { + _type = "string", + _name = "a valid dependency string", + _pattern = "%s*([a-zA-Z0-9%.%-%_]*/?[a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*([^/]*)", + }, + }, + test_dependencies = { + platforms = type_check.MAGIC_PLATFORMS, + _any = { + _type = "string", + _name = "a valid dependency string", + _pattern = "%s*([a-zA-Z0-9%.%-%_]*/?[a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*([^/]*)", + }, + }, + build = { + _mandatory = false, + }, + test = { + platforms = type_check.MAGIC_PLATFORMS, + type = { _type = "string" }, + _more = true, + }, + } +}) + +-- type_rockspec.order = {"rockspec_format", "package", "version", +-- { "source", { "url", "tag", "branch", "md5" } }, +-- { "description", {"summary", "detailed", "homepage", "license" } }, +-- "supported_platforms", "dependencies", "build_dependencies", "external_dependencies", +-- { "build", {"type", "modules", "copy_directories", "platforms"} }, +-- "test_dependencies", { "test", {"type"} }, +-- "hooks"} + +type_rockspec.order = { + "rockspec_format", + "package", + "version", + "source", + "description", + "supported_platforms", + "dependencies", + "build_dependencies", + "external_dependencies", + "build", + "test_dependencies", + "test", + "hooks", + sub_orders = { + ["source"] = { "url", "tag", "branch", "md5" }, + ["description"] = {"summary", "detailed", "homepage", "license" }, + ["build"] = { "type", "modules", "copy_directories", "platforms" }, + ["test"] = { "type" } + } +} + +local function check_rockspec_using_version(rockspec, globals, version) + local schema = rockspec_formats[version] + if not schema then + return nil, "unknown rockspec format " .. version + end + local ok, err = type_check.check_undeclared_globals(globals, schema) + if ok then + ok, err = type_check.type_check_table(version, rockspec, schema, "") + end + if ok then + return true + else + return nil, err + end +end + +--- Type check a rockspec table. +-- Verify the correctness of elements from a +-- rockspec table, reporting on unknown fields and type +-- mismatches. +-- @return boolean or (nil, string): true if type checking +-- succeeded, or nil and an error message if it failed. +function type_rockspec.check(rockspec, globals) + assert(type(rockspec) == "table") + + local version = rockspec.rockspec_format or "1.0" + local ok, err = check_rockspec_using_version(rockspec, globals, version) + if ok then + return true + end + + -- Rockspec parsing failed. + -- Let's see if it would pass using a later version. + + local found = false + for _, v in ipairs(versions) do + if not found then + if v == version then + found = true + end + else + local v_ok, v_err = check_rockspec_using_version(rockspec, globals, v) + if v_ok then + return nil, err .. " (using rockspec format " .. version .. " -- " .. + [[adding 'rockspec_format = "]] .. v .. [["' to the rockspec ]] .. + [[will fix this)]] + end + end + end + + return nil, err .. " (using rockspec format " .. version .. ")" +end + +return type_rockspec -- cgit v1.2.3-55-g6feb