diff options
| author | Hisham Muhammad <hisham@gobolinux.org> | 2018-06-06 14:27:07 -0300 |
|---|---|---|
| committer | Hisham Muhammad <hisham@gobolinux.org> | 2018-06-14 14:06:51 -0300 |
| commit | f8c877d486af39fc563b8a4107092682d49e4ae9 (patch) | |
| tree | 808ae48d9d00aac713696093a251b6321fb68606 | |
| parent | 2d739d1ab3c0027fb677ee6007bc9269800eb18d (diff) | |
| download | luarocks-f8c877d486af39fc563b8a4107092682d49e4ae9.tar.gz luarocks-f8c877d486af39fc563b8a4107092682d49e4ae9.tar.bz2 luarocks-f8c877d486af39fc563b8a4107092682d49e4ae9.zip | |
Refactor type checking to allow mandatory attribute to be dropped
| -rw-r--r-- | src/luarocks/type/manifest.lua | 100 | ||||
| -rw-r--r-- | src/luarocks/type/rockspec.lua | 222 | ||||
| -rw-r--r-- | src/luarocks/type_check.lua | 82 | ||||
| -rw-r--r-- | src/luarocks/util.lua | 13 |
4 files changed, 251 insertions, 166 deletions
diff --git a/src/luarocks/type/manifest.lua b/src/luarocks/type/manifest.lua index f58ff984..407428b2 100644 --- a/src/luarocks/type/manifest.lua +++ b/src/luarocks/type/manifest.lua | |||
| @@ -2,59 +2,57 @@ local type_manifest = {} | |||
| 2 | 2 | ||
| 3 | local type_check = require("luarocks.type_check") | 3 | local type_check = require("luarocks.type_check") |
| 4 | 4 | ||
| 5 | local number_1 = type_check.number_1 | 5 | local manifest_formats = type_check.declare_schemas({ |
| 6 | local string_1 = type_check.string_1 | 6 | ["1.0"] = { |
| 7 | local mandatory_string_1 = type_check.mandatory_string_1 | 7 | repository = { |
| 8 | 8 | _mandatory = true, | |
| 9 | local manifest_types = { | 9 | -- packages |
| 10 | repository = { | ||
| 11 | _mandatory = true, | ||
| 12 | -- packages | ||
| 13 | _any = { | ||
| 14 | -- versions | ||
| 15 | _any = { | 10 | _any = { |
| 16 | -- items | 11 | -- versions |
| 17 | _any = { | 12 | _any = { |
| 18 | arch = mandatory_string_1, | 13 | -- items |
| 19 | modules = { _any = string_1 }, | 14 | _any = { |
| 20 | commands = { _any = string_1 }, | 15 | arch = { _type = "string", _mandatory = true }, |
| 21 | dependencies = { _any = string_1 }, | 16 | modules = { _any = { _type = "string" } }, |
| 22 | -- TODO: to be extended with more metadata. | 17 | commands = { _any = { _type = "string" } }, |
| 18 | dependencies = { _any = { _type = "string" } }, | ||
| 19 | -- TODO: to be extended with more metadata. | ||
| 20 | } | ||
| 23 | } | 21 | } |
| 24 | } | 22 | } |
| 25 | } | 23 | }, |
| 26 | }, | 24 | modules = { |
| 27 | modules = { | 25 | _mandatory = true, |
| 28 | _mandatory = true, | 26 | -- modules |
| 29 | -- modules | ||
| 30 | _any = { | ||
| 31 | -- providers | ||
| 32 | _any = string_1 | ||
| 33 | } | ||
| 34 | }, | ||
| 35 | commands = { | ||
| 36 | _mandatory = true, | ||
| 37 | -- modules | ||
| 38 | _any = { | ||
| 39 | -- commands | ||
| 40 | _any = string_1 | ||
| 41 | } | ||
| 42 | }, | ||
| 43 | dependencies = { | ||
| 44 | -- each module | ||
| 45 | _any = { | ||
| 46 | -- each version | ||
| 47 | _any = { | 27 | _any = { |
| 48 | -- each dependency | 28 | -- providers |
| 29 | _any = { _type = "string" } | ||
| 30 | } | ||
| 31 | }, | ||
| 32 | commands = { | ||
| 33 | _mandatory = true, | ||
| 34 | -- modules | ||
| 35 | _any = { | ||
| 36 | -- commands | ||
| 37 | _any = { _type = "string" } | ||
| 38 | } | ||
| 39 | }, | ||
| 40 | dependencies = { | ||
| 41 | -- each module | ||
| 42 | _any = { | ||
| 43 | -- each version | ||
| 49 | _any = { | 44 | _any = { |
| 50 | name = string_1, | 45 | -- each dependency |
| 51 | constraints = { | 46 | _any = { |
| 52 | _any = { | 47 | name = { _type = "string" }, |
| 53 | no_upgrade = { _type = "boolean" }, | 48 | constraints = { |
| 54 | op = string_1, | 49 | _any = { |
| 55 | version = { | 50 | no_upgrade = { _type = "boolean" }, |
| 56 | string = string_1, | 51 | op = { _type = "string" }, |
| 57 | _any = number_1, | 52 | version = { |
| 53 | string = { _type = "string" }, | ||
| 54 | _any = { _type = "number" }, | ||
| 55 | } | ||
| 58 | } | 56 | } |
| 59 | } | 57 | } |
| 60 | } | 58 | } |
| @@ -62,8 +60,7 @@ local manifest_types = { | |||
| 62 | } | 60 | } |
| 63 | } | 61 | } |
| 64 | } | 62 | } |
| 65 | } | 63 | }) |
| 66 | |||
| 67 | 64 | ||
| 68 | --- Type check a manifest table. | 65 | --- Type check a manifest table. |
| 69 | -- Verify the correctness of elements from a | 66 | -- Verify the correctness of elements from a |
| @@ -73,9 +70,10 @@ local manifest_types = { | |||
| 73 | -- succeeded, or nil and an error message if it failed. | 70 | -- succeeded, or nil and an error message if it failed. |
| 74 | function type_manifest.check(manifest, globals) | 71 | function type_manifest.check(manifest, globals) |
| 75 | assert(type(manifest) == "table") | 72 | assert(type(manifest) == "table") |
| 76 | local ok, err = type_check.check_undeclared_globals(globals, manifest_types) | 73 | local format = manifest_formats["1.0"] |
| 74 | local ok, err = type_check.check_undeclared_globals(globals, format) | ||
| 77 | if not ok then return nil, err end | 75 | if not ok then return nil, err end |
| 78 | return type_check.type_check_table("1.0", manifest, manifest_types, "") | 76 | return type_check.type_check_table("1.0", manifest, format, "") |
| 79 | end | 77 | end |
| 80 | 78 | ||
| 81 | return type_manifest | 79 | return type_manifest |
diff --git a/src/luarocks/type/rockspec.lua b/src/luarocks/type/rockspec.lua index 16ab911c..8b2bdffa 100644 --- a/src/luarocks/type/rockspec.lua +++ b/src/luarocks/type/rockspec.lua | |||
| @@ -4,18 +4,11 @@ local type_check = require("luarocks.type_check") | |||
| 4 | 4 | ||
| 5 | type_rockspec.rockspec_format = "3.0" | 5 | type_rockspec.rockspec_format = "3.0" |
| 6 | 6 | ||
| 7 | local string_1 = type_check.string_1 | ||
| 8 | local mandatory_string_1 = type_check.mandatory_string_1 | ||
| 9 | |||
| 10 | local string_3 = { _type = "string", _version = "3.0" } | ||
| 11 | local list_of_strings_3 = { _any = string_3, _version = "3.0" } | ||
| 12 | |||
| 13 | -- Syntax for type-checking tables: | 7 | -- Syntax for type-checking tables: |
| 14 | -- | 8 | -- |
| 15 | -- A type-checking table describes typing data for a value. | 9 | -- A type-checking table describes typing data for a value. |
| 16 | -- Any key starting with an underscore has a special meaning: | 10 | -- Any key starting with an underscore has a special meaning: |
| 17 | -- _type (string) is the Lua type of the value. Default is "table". | 11 | -- _type (string) is the Lua type of the value. Default is "table". |
| 18 | -- _version (string) is the minimum rockspec_version that supports this value. Default is "1.0". | ||
| 19 | -- _mandatory (boolean) indicates if the value is a mandatory key in its container table. Default is false. | 12 | -- _mandatory (boolean) indicates if the value is a mandatory key in its container table. Default is false. |
| 20 | -- For "string" types only: | 13 | -- For "string" types only: |
| 21 | -- _pattern (string) is the string-matching pattern, valid for string types only. Default is ".*". | 14 | -- _pattern (string) is the string-matching pattern, valid for string types only. Default is ".*". |
| @@ -24,110 +17,123 @@ local list_of_strings_3 = { _any = string_3, _version = "3.0" } | |||
| 24 | -- _more (boolean) indicates that the table accepts unspecified keys and does not type-check them. | 17 | -- _more (boolean) indicates that the table accepts unspecified keys and does not type-check them. |
| 25 | -- Any other string keys that don't start with an underscore represent known keys and are type-checking tables, recursively checked. | 18 | -- Any other string keys that don't start with an underscore represent known keys and are type-checking tables, recursively checked. |
| 26 | 19 | ||
| 27 | local rockspec_types = { | 20 | local rockspec_formats = type_check.declare_schemas({ |
| 28 | rockspec_format = string_1, | 21 | ["1.0"] = { |
| 29 | package = mandatory_string_1, | 22 | rockspec_format = { _type = "string" }, |
| 30 | version = { _type = "string", _pattern = "[%w.]+-[%d]+", _mandatory = true }, | 23 | package = { _type = "string", _mandatory = true }, |
| 31 | description = { | 24 | version = { _type = "string", _pattern = "[%w.]+-[%d]+", _mandatory = true }, |
| 32 | summary = string_1, | 25 | description = { |
| 33 | detailed = string_1, | 26 | summary = { _type = "string" }, |
| 34 | homepage = string_1, | 27 | detailed = { _type = "string" }, |
| 35 | license = string_1, | 28 | homepage = { _type = "string" }, |
| 36 | maintainer = string_1, | 29 | license = { _type = "string" }, |
| 37 | labels = list_of_strings_3, | 30 | maintainer = { _type = "string" }, |
| 38 | issues_url = string_3, | 31 | }, |
| 39 | }, | 32 | dependencies = { |
| 40 | dependencies = { | 33 | platforms = type_check.MAGIC_PLATFORMS, |
| 41 | platforms = {}, -- recursively defined below | 34 | _any = { |
| 42 | _any = { | 35 | _type = "string", |
| 43 | _type = "string", | 36 | _name = "a valid dependency string", |
| 44 | _name = "a valid dependency string", | 37 | _pattern = "%s*([a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*([^/]*)", |
| 45 | _patterns = { | ||
| 46 | ["1.0"] = "%s*([a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*([^/]*)", | ||
| 47 | ["3.0"] = "%s*([a-zA-Z0-9%.%-%_]*/?[a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*([^/]*)", | ||
| 48 | }, | 38 | }, |
| 49 | }, | 39 | }, |
| 50 | }, | 40 | supported_platforms = { |
| 51 | build_dependencies = { | 41 | _any = { _type = "string" }, |
| 52 | _version = "3.0", | ||
| 53 | platforms = {}, -- recursively defined below | ||
| 54 | _any = { | ||
| 55 | _type = "string", | ||
| 56 | _name = "a valid dependency string", | ||
| 57 | _pattern = "%s*([a-zA-Z0-9%.%-%_]*/?[a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*([^/]*)", | ||
| 58 | }, | 42 | }, |
| 59 | }, | 43 | external_dependencies = { |
| 60 | test_dependencies = { | 44 | platforms = type_check.MAGIC_PLATFORMS, |
| 61 | _version = "3.0", | 45 | _any = { |
| 62 | platforms = {}, -- recursively defined below | 46 | program = { _type = "string" }, |
| 63 | _any = { | 47 | header = { _type = "string" }, |
| 64 | _type = "string", | 48 | library = { _type = "string" }, |
| 65 | _name = "a valid dependency string", | 49 | } |
| 66 | _pattern = "%s*([a-zA-Z0-9%.%-%_]*/?[a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*([^/]*)", | 50 | }, |
| 51 | source = { | ||
| 52 | _mandatory = true, | ||
| 53 | platforms = type_check.MAGIC_PLATFORMS, | ||
| 54 | url = { _type = "string", _mandatory = true }, | ||
| 55 | md5 = { _type = "string" }, | ||
| 56 | file = { _type = "string" }, | ||
| 57 | dir = { _type = "string" }, | ||
| 58 | tag = { _type = "string" }, | ||
| 59 | branch = { _type = "string" }, | ||
| 60 | module = { _type = "string" }, | ||
| 61 | cvs_tag = { _type = "string" }, | ||
| 62 | cvs_module = { _type = "string" }, | ||
| 63 | }, | ||
| 64 | build = { | ||
| 65 | platforms = type_check.MAGIC_PLATFORMS, | ||
| 66 | type = { _type = "string" }, | ||
| 67 | install = { | ||
| 68 | lua = { | ||
| 69 | _more = true | ||
| 70 | }, | ||
| 71 | lib = { | ||
| 72 | _more = true | ||
| 73 | }, | ||
| 74 | conf = { | ||
| 75 | _more = true | ||
| 76 | }, | ||
| 77 | bin = { | ||
| 78 | _more = true | ||
| 79 | } | ||
| 80 | }, | ||
| 81 | copy_directories = { | ||
| 82 | _any = { _type = "string" }, | ||
| 83 | }, | ||
| 84 | _more = true, | ||
| 85 | _mandatory = true | ||
| 86 | }, | ||
| 87 | hooks = { | ||
| 88 | platforms = type_check.MAGIC_PLATFORMS, | ||
| 89 | post_install = { _type = "string" }, | ||
| 67 | }, | 90 | }, |
| 68 | }, | 91 | }, |
| 69 | supported_platforms = { | 92 | |
| 70 | _any = string_1, | 93 | ["1.1"] = { |
| 71 | }, | 94 | deploy = { |
| 72 | external_dependencies = { | 95 | wrap_bin_scripts = { _type = "boolean" }, |
| 73 | platforms = {}, -- recursively defined below | ||
| 74 | _any = { | ||
| 75 | program = string_1, | ||
| 76 | header = string_1, | ||
| 77 | library = string_1, | ||
| 78 | } | 96 | } |
| 79 | }, | 97 | }, |
| 80 | source = { | 98 | |
| 81 | _mandatory = true, | 99 | ["3.0"] = { |
| 82 | platforms = {}, -- recursively defined below | 100 | description = { |
| 83 | url = mandatory_string_1, | 101 | labels = { |
| 84 | md5 = string_1, | 102 | _any = { _type = "string" } |
| 85 | file = string_1, | ||
| 86 | dir = string_1, | ||
| 87 | tag = string_1, | ||
| 88 | branch = string_1, | ||
| 89 | module = string_1, | ||
| 90 | cvs_tag = string_1, | ||
| 91 | cvs_module = string_1, | ||
| 92 | }, | ||
| 93 | build = { | ||
| 94 | platforms = {}, -- recursively defined below | ||
| 95 | type = string_1, | ||
| 96 | install = { | ||
| 97 | lua = { | ||
| 98 | _more = true | ||
| 99 | }, | 103 | }, |
| 100 | lib = { | 104 | issues_url = { _type = "string" }, |
| 101 | _more = true | 105 | }, |
| 106 | dependencies = { | ||
| 107 | _any = { | ||
| 108 | _pattern = "%s*([a-zA-Z0-9%.%-%_]*/?[a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*([^/]*)", | ||
| 102 | }, | 109 | }, |
| 103 | conf = { | 110 | }, |
| 104 | _more = true | 111 | build_dependencies = { |
| 112 | platforms = type_check.MAGIC_PLATFORMS, | ||
| 113 | _any = { | ||
| 114 | _type = "string", | ||
| 115 | _name = "a valid dependency string", | ||
| 116 | _pattern = "%s*([a-zA-Z0-9%.%-%_]*/?[a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*([^/]*)", | ||
| 117 | }, | ||
| 118 | }, | ||
| 119 | test_dependencies = { | ||
| 120 | platforms = type_check.MAGIC_PLATFORMS, | ||
| 121 | _any = { | ||
| 122 | _type = "string", | ||
| 123 | _name = "a valid dependency string", | ||
| 124 | _pattern = "%s*([a-zA-Z0-9%.%-%_]*/?[a-zA-Z0-9][a-zA-Z0-9%.%-%_]*)%s*([^/]*)", | ||
| 105 | }, | 125 | }, |
| 106 | bin = { | ||
| 107 | _more = true | ||
| 108 | } | ||
| 109 | }, | 126 | }, |
| 110 | copy_directories = { | 127 | build = { |
| 111 | _any = string_1, | 128 | _mandatory = false, |
| 129 | }, | ||
| 130 | test = { | ||
| 131 | platforms = type_check.MAGIC_PLATFORMS, | ||
| 132 | type = { _type = "string" }, | ||
| 133 | _more = true, | ||
| 112 | }, | 134 | }, |
| 113 | _more = true, | ||
| 114 | _mandatory = true | ||
| 115 | }, | ||
| 116 | test = { | ||
| 117 | _version = "3.0", | ||
| 118 | platforms = {}, -- recursively defined below | ||
| 119 | type = string_1, | ||
| 120 | _more = true, | ||
| 121 | }, | ||
| 122 | hooks = { | ||
| 123 | platforms = {}, -- recursively defined below | ||
| 124 | post_install = string_1, | ||
| 125 | }, | ||
| 126 | deploy = { | ||
| 127 | _version = "1.1", | ||
| 128 | wrap_bin_scripts = { _type = "boolean", _version = "1.1" }, | ||
| 129 | } | 135 | } |
| 130 | } | 136 | }) |
| 131 | 137 | ||
| 132 | type_rockspec.order = {"rockspec_format", "package", "version", | 138 | type_rockspec.order = {"rockspec_format", "package", "version", |
| 133 | { "source", { "url", "tag", "branch", "md5" } }, | 139 | { "source", { "url", "tag", "branch", "md5" } }, |
| @@ -137,14 +143,6 @@ type_rockspec.order = {"rockspec_format", "package", "version", | |||
| 137 | "test_dependencies", { "test", {"type"} }, | 143 | "test_dependencies", { "test", {"type"} }, |
| 138 | "hooks"} | 144 | "hooks"} |
| 139 | 145 | ||
| 140 | rockspec_types.build.platforms._any = rockspec_types.build | ||
| 141 | rockspec_types.dependencies.platforms._any = rockspec_types.dependencies | ||
| 142 | rockspec_types.build_dependencies.platforms._any = rockspec_types.build_dependencies | ||
| 143 | rockspec_types.external_dependencies.platforms._any = rockspec_types.external_dependencies | ||
| 144 | rockspec_types.source.platforms._any = rockspec_types.source | ||
| 145 | rockspec_types.hooks.platforms._any = rockspec_types.hooks | ||
| 146 | rockspec_types.test.platforms._any = rockspec_types.test | ||
| 147 | |||
| 148 | --- Type check a rockspec table. | 146 | --- Type check a rockspec table. |
| 149 | -- Verify the correctness of elements from a | 147 | -- Verify the correctness of elements from a |
| 150 | -- rockspec table, reporting on unknown fields and type | 148 | -- rockspec table, reporting on unknown fields and type |
| @@ -153,17 +151,19 @@ rockspec_types.test.platforms._any = rockspec_types.test | |||
| 153 | -- succeeded, or nil and an error message if it failed. | 151 | -- succeeded, or nil and an error message if it failed. |
| 154 | function type_rockspec.check(rockspec, globals) | 152 | function type_rockspec.check(rockspec, globals) |
| 155 | assert(type(rockspec) == "table") | 153 | assert(type(rockspec) == "table") |
| 156 | if not rockspec.rockspec_format then | 154 | local version = rockspec.rockspec_format or "1.0" |
| 157 | rockspec.rockspec_format = "1.0" | 155 | local schema = rockspec_formats[version] |
| 156 | if not schema then | ||
| 157 | return nil, "unknown rockspec format " .. version | ||
| 158 | end | 158 | end |
| 159 | local ok, err = type_check.check_undeclared_globals(globals, rockspec_types) | 159 | local ok, err = type_check.check_undeclared_globals(globals, schema) |
| 160 | if ok then | 160 | if ok then |
| 161 | ok, err = type_check.type_check_table(rockspec.rockspec_format, rockspec, rockspec_types, "") | 161 | ok, err = type_check.type_check_table(version, rockspec, schema, "") |
| 162 | end | 162 | end |
| 163 | if ok then | 163 | if ok then |
| 164 | return true | 164 | return true |
| 165 | end | 165 | end |
| 166 | return nil, err .. " (rockspec format " .. rockspec.rockspec_format .. ")" | 166 | return nil, err .. " (rockspec format " .. version .. ")" |
| 167 | end | 167 | end |
| 168 | 168 | ||
| 169 | return type_rockspec | 169 | return type_rockspec |
diff --git a/src/luarocks/type_check.lua b/src/luarocks/type_check.lua index ebd59f85..827c64b6 100644 --- a/src/luarocks/type_check.lua +++ b/src/luarocks/type_check.lua | |||
| @@ -3,12 +3,86 @@ local type_check = {} | |||
| 3 | 3 | ||
| 4 | local cfg = require("luarocks.core.cfg") | 4 | local cfg = require("luarocks.core.cfg") |
| 5 | local vers = require("luarocks.core.vers") | 5 | local vers = require("luarocks.core.vers") |
| 6 | local util = require("luarocks.util") | ||
| 6 | local require = nil | 7 | local require = nil |
| 7 | -------------------------------------------------------------------------------- | 8 | -------------------------------------------------------------------------------- |
| 8 | 9 | ||
| 9 | type_check.string_1 = { _type = "string" } | 10 | type_check.MAGIC_PLATFORMS = {} |
| 10 | type_check.number_1 = { _type = "number" } | 11 | |
| 11 | type_check.mandatory_string_1 = { _type = "string", _mandatory = true } | 12 | do |
| 13 | local function fill_in_version(tbl, version) | ||
| 14 | for _, v in pairs(tbl) do | ||
| 15 | if type(v) == "table" then | ||
| 16 | if v._version == nil then | ||
| 17 | v._version = version | ||
| 18 | end | ||
| 19 | fill_in_version(v) | ||
| 20 | end | ||
| 21 | end | ||
| 22 | end | ||
| 23 | |||
| 24 | local function expand_magic_platforms(tbl) | ||
| 25 | for k,v in pairs(tbl) do | ||
| 26 | if v == type_check.MAGIC_PLATFORMS then | ||
| 27 | tbl[k] = { | ||
| 28 | _any = util.deep_copy(tbl) | ||
| 29 | } | ||
| 30 | tbl[k]._any[v] = nil | ||
| 31 | elseif type(v) == "table" then | ||
| 32 | expand_magic_platforms(v) | ||
| 33 | end | ||
| 34 | end | ||
| 35 | end | ||
| 36 | |||
| 37 | local function merge_under(dst, src) | ||
| 38 | for k, v in pairs(src) do | ||
| 39 | if dst[k] == nil then | ||
| 40 | if type(dst[k]) == "table" then | ||
| 41 | util.deep_merge(dst[k], v) | ||
| 42 | else | ||
| 43 | dst[k] = v | ||
| 44 | end | ||
| 45 | end | ||
| 46 | end | ||
| 47 | end | ||
| 48 | |||
| 49 | -- Build a table of schemas. | ||
| 50 | -- @param versions a table where each key is a version number as a string, | ||
| 51 | -- and the value is a schema specification. Schema versions are considered | ||
| 52 | -- incremental: version "2.0" only needs to specify what's new/changed from | ||
| 53 | -- version "1.0". | ||
| 54 | function type_check.declare_schemas(versions) | ||
| 55 | local schemas = {} | ||
| 56 | local parent_version | ||
| 57 | |||
| 58 | local version_list = {} | ||
| 59 | -- FIXME sorting lexicographically! "1.9" > "1.10" | ||
| 60 | for version, schema in util.sortedpairs(versions) do | ||
| 61 | table.insert(version_list, version) | ||
| 62 | if parent_version ~= nil then | ||
| 63 | local copy = util.deep_copy(schemas[parent_version]) | ||
| 64 | util.deep_merge(copy, schema) | ||
| 65 | schemas[version] = copy | ||
| 66 | else | ||
| 67 | schemas[version] = schema | ||
| 68 | end | ||
| 69 | fill_in_version(schemas[version], version) | ||
| 70 | expand_magic_platforms(schemas[version]) | ||
| 71 | parent_version = version | ||
| 72 | end | ||
| 73 | |||
| 74 | -- Merge future versions as fallbacks under the old versions, | ||
| 75 | -- so that error messages can inform users when they try | ||
| 76 | -- to use new features without bumping rockspec_format in their rockspecs. | ||
| 77 | for i = #version_list, 2, -1 do | ||
| 78 | merge_under(schemas[version_list[i - 1]], schemas[version_list[i]]) | ||
| 79 | end | ||
| 80 | |||
| 81 | return schemas | ||
| 82 | end | ||
| 83 | end | ||
| 84 | |||
| 85 | -------------------------------------------------------------------------------- | ||
| 12 | 86 | ||
| 13 | local function check_version(version, typetbl, context) | 87 | local function check_version(version, typetbl, context) |
| 14 | local typetbl_version = typetbl._version or "1.0" | 88 | local typetbl_version = typetbl._version or "1.0" |
| @@ -55,7 +129,7 @@ local function type_check_item(version, item, typetbl, context) | |||
| 55 | if item_type ~= "string" then | 129 | if item_type ~= "string" then |
| 56 | return nil, "Type mismatch on field "..context..": expected a string, got "..item_type | 130 | return nil, "Type mismatch on field "..context..": expected a string, got "..item_type |
| 57 | end | 131 | end |
| 58 | local pattern = (typetbl._patterns and typetbl._patterns[version]) or typetbl._pattern | 132 | local pattern = typetbl._pattern |
| 59 | if pattern then | 133 | if pattern then |
| 60 | if not item:match("^"..pattern.."$") then | 134 | if not item:match("^"..pattern.."$") then |
| 61 | local what = typetbl._name or ("'"..pattern.."'") | 135 | local what = typetbl._name or ("'"..pattern.."'") |
diff --git a/src/luarocks/util.lua b/src/luarocks/util.lua index cd946451..f5506f53 100644 --- a/src/luarocks/util.lua +++ b/src/luarocks/util.lua | |||
| @@ -15,6 +15,7 @@ util.keys = core.keys | |||
| 15 | util.printerr = core.printerr | 15 | util.printerr = core.printerr |
| 16 | util.sortedpairs = core.sortedpairs | 16 | util.sortedpairs = core.sortedpairs |
| 17 | util.warning = core.warning | 17 | util.warning = core.warning |
| 18 | util.deep_merge = core.deep_merge | ||
| 18 | 19 | ||
| 19 | local unpack = unpack or table.unpack | 20 | local unpack = unpack or table.unpack |
| 20 | 21 | ||
| @@ -479,4 +480,16 @@ function util.split_namespace(ns_name) | |||
| 479 | return ns_name | 480 | return ns_name |
| 480 | end | 481 | end |
| 481 | 482 | ||
| 483 | function util.deep_copy(tbl) | ||
| 484 | local copy = {} | ||
| 485 | for k, v in pairs(tbl) do | ||
| 486 | if type(v) == "table" then | ||
| 487 | copy[k] = util.deep_copy(v) | ||
| 488 | else | ||
| 489 | copy[k] = v | ||
| 490 | end | ||
| 491 | end | ||
| 492 | return copy | ||
| 493 | end | ||
| 494 | |||
| 482 | return util | 495 | return util |
