diff options
| author | Hisham Muhammad <hisham@gobolinux.org> | 2018-06-05 01:58:48 -0300 |
|---|---|---|
| committer | Hisham Muhammad <hisham@gobolinux.org> | 2018-06-06 12:39:23 -0300 |
| commit | 35d139407db87349e8ccc11e0e1696b610d9582e (patch) | |
| tree | 4b58ebeb75c96a83cab3505f2cf09c77627d2f2a /src | |
| parent | 03223a93763675520a2b5e16bb6ffeb871de332a (diff) | |
| download | luarocks-35d139407db87349e8ccc11e0e1696b610d9582e.tar.gz luarocks-35d139407db87349e8ccc11e0e1696b610d9582e.tar.bz2 luarocks-35d139407db87349e8ccc11e0e1696b610d9582e.zip | |
General refactor introducing Rockspec and Build.Opts objects
Adds a Rockspec object responsible for constructing all Rockspec
tables in the manner of the Queries and Results objects, and
a type-checked Build.Opts tables for build options, since
the number of attributes passed around was getting out of hand.
This allowed a major cleanup in the luarocks.build,
luarocks.fetch and luarocks.cmd.write_rockspec modules.
Diffstat (limited to 'src')
28 files changed, 754 insertions, 615 deletions
diff --git a/src/luarocks/build.lua b/src/luarocks/build.lua index 25e73b0d..ac4ecfad 100644 --- a/src/luarocks/build.lua +++ b/src/luarocks/build.lua | |||
| @@ -12,26 +12,226 @@ local cfg = require("luarocks.core.cfg") | |||
| 12 | local repos = require("luarocks.repos") | 12 | local repos = require("luarocks.repos") |
| 13 | local writer = require("luarocks.manif.writer") | 13 | local writer = require("luarocks.manif.writer") |
| 14 | 14 | ||
| 15 | --- Install files to a given location. | 15 | local opts_mt = {} |
| 16 | -- Takes a table where the array part is a list of filenames to be copied. | 16 | |
| 17 | -- In the hash part, other keys, if is_module_path is set, are identifiers | 17 | opts_mt.__index = opts_mt |
| 18 | -- in Lua module format, to indicate which subdirectory the file should be | 18 | |
| 19 | -- copied to. For example, install_files({["foo.bar"] = "src/bar.lua"}, "boo") | 19 | function opts_mt.type() |
| 20 | -- will copy src/bar.lua to boo/foo. | 20 | return "build.opts" |
| 21 | -- @param files table or nil: A table containing a list of files to copy in | 21 | end |
| 22 | -- the format described above. If nil is passed, this function is a no-op. | 22 | |
| 23 | -- Directories should be delimited by forward slashes as in internet URLs. | 23 | function build.opts(opts) |
| 24 | -- @param location string: The base directory files should be copied to. | 24 | local valid_opts = { |
| 25 | -- @param is_module_path boolean: True if string keys in files should be | 25 | need_to_fetch = "boolean", |
| 26 | -- interpreted as dotted module paths. | 26 | minimal_mode = "boolean", |
| 27 | -- @param perms string ("read" or "exec"): Permissions of the newly created files installed. | 27 | deps_mode = "string", |
| 28 | -- Directories are always created with the default permissions. | 28 | build_only_deps = "boolean", |
| 29 | -- @return boolean or (nil, string): True if succeeded or | 29 | namespace = "string?", |
| 30 | -- nil and an error message. | 30 | branch = "boolean", |
| 31 | local function install_files(files, location, is_module_path, perms) | 31 | } |
| 32 | assert(type(files) == "table" or not files) | 32 | for k, v in pairs(opts) do |
| 33 | assert(type(location) == "string") | 33 | local tv = type(v) |
| 34 | if files then | 34 | if not valid_opts[k] then |
| 35 | error("invalid build option: "..k) | ||
| 36 | end | ||
| 37 | local vo, optional = valid_opts[k]:match("^(.-)(%??)$") | ||
| 38 | if not (tv == vo or (optional == "?" and tv == nil)) then | ||
| 39 | error("invalid type build option: "..k.." - got "..tv..", expected "..vo) | ||
| 40 | end | ||
| 41 | end | ||
| 42 | for k, v in pairs(valid_opts) do | ||
| 43 | if (not v:find("?", 1, true)) and opts[k] == nil then | ||
| 44 | error("missing build option: "..k) | ||
| 45 | end | ||
| 46 | end | ||
| 47 | return setmetatable(opts, opts_mt) | ||
| 48 | end | ||
| 49 | |||
| 50 | do | ||
| 51 | --- Write to the current directory the contents of a table, | ||
| 52 | -- where each key is a file name and its value is the file content. | ||
| 53 | -- @param files table: The table of files to be written. | ||
| 54 | local function extract_from_rockspec(files) | ||
| 55 | for name, content in pairs(files) do | ||
| 56 | local fd = io.open(dir.path(fs.current_dir(), name), "w+") | ||
| 57 | fd:write(content) | ||
| 58 | fd:close() | ||
| 59 | end | ||
| 60 | end | ||
| 61 | |||
| 62 | --- Applies patches inlined in the build.patches section | ||
| 63 | -- and extracts files inlined in the build.extra_files section | ||
| 64 | -- of a rockspec. | ||
| 65 | -- @param rockspec table: A rockspec table. | ||
| 66 | -- @return boolean or (nil, string): True if succeeded or | ||
| 67 | -- nil and an error message. | ||
| 68 | function build.apply_patches(rockspec) | ||
| 69 | assert(rockspec:type() == "rockspec") | ||
| 70 | |||
| 71 | if rockspec.build.extra_files then | ||
| 72 | extract_from_rockspec(rockspec.build.extra_files) | ||
| 73 | end | ||
| 74 | if rockspec.build.patches then | ||
| 75 | extract_from_rockspec(rockspec.build.patches) | ||
| 76 | for patch, patchdata in util.sortedpairs(rockspec.build.patches) do | ||
| 77 | util.printout("Applying patch "..patch.."...") | ||
| 78 | local create_delete = rockspec:format_is_at_least("3.0") | ||
| 79 | local ok, err = fs.apply_patch(tostring(patch), patchdata, create_delete) | ||
| 80 | if not ok then | ||
| 81 | return nil, "Failed applying patch "..patch | ||
| 82 | end | ||
| 83 | end | ||
| 84 | end | ||
| 85 | return true | ||
| 86 | end | ||
| 87 | end | ||
| 88 | |||
| 89 | local function check_macosx_deployment_target(rockspec) | ||
| 90 | local target = rockspec.build.macosx_deployment_target | ||
| 91 | local function minor(version) | ||
| 92 | return tonumber(version and version:match("^[^.]+%.([^.]+)")) | ||
| 93 | end | ||
| 94 | local function patch_variable(var) | ||
| 95 | if rockspec.variables[var]:match("MACOSX_DEPLOYMENT_TARGET") then | ||
| 96 | rockspec.variables[var] = (rockspec.variables[var]):gsub("MACOSX_DEPLOYMENT_TARGET=[^ ]*", "MACOSX_DEPLOYMENT_TARGET="..target) | ||
| 97 | else | ||
| 98 | rockspec.variables[var] = "env MACOSX_DEPLOYMENT_TARGET="..target.." "..rockspec.variables[var] | ||
| 99 | end | ||
| 100 | end | ||
| 101 | if cfg.platforms.macosx and rockspec:format_is_at_least("3.0") and target then | ||
| 102 | local version = util.popen_read("sw_vers -productVersion") | ||
| 103 | local versionminor = minor(version) | ||
| 104 | local targetminor = minor(target) | ||
| 105 | if targetminor > versionminor then | ||
| 106 | return nil, ("This rock requires Mac OSX 10.%d, and you are running 10.%d."):format(targetminor, versionminor) | ||
| 107 | end | ||
| 108 | patch_variable("CC", target) | ||
| 109 | patch_variable("LD", target) | ||
| 110 | end | ||
| 111 | return true | ||
| 112 | end | ||
| 113 | |||
| 114 | local function process_dependencies(rockspec, opts) | ||
| 115 | if not opts.build_only_deps then | ||
| 116 | local ok, err, errcode = deps.check_external_deps(rockspec, "build") | ||
| 117 | if err then | ||
| 118 | return nil, err, errcode | ||
| 119 | end | ||
| 120 | end | ||
| 121 | if opts.deps_mode == "none" then | ||
| 122 | util.warning("skipping dependency checks.") | ||
| 123 | return true | ||
| 124 | end | ||
| 125 | if not opts.build_only_deps then | ||
| 126 | if next(rockspec.build_dependencies) then | ||
| 127 | local ok, err, errcode = deps.fulfill_dependencies(rockspec, "build_dependencies", opts.deps_mode) | ||
| 128 | if err then | ||
| 129 | return nil, err, errcode | ||
| 130 | end | ||
| 131 | end | ||
| 132 | end | ||
| 133 | local ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", opts.deps_mode) | ||
| 134 | if err then | ||
| 135 | return nil, err, errcode | ||
| 136 | end | ||
| 137 | return true | ||
| 138 | end | ||
| 139 | |||
| 140 | local function fetch_and_change_to_source_dir(rockspec, opts) | ||
| 141 | if opts.minimal_mode then | ||
| 142 | return true | ||
| 143 | end | ||
| 144 | if opts.need_to_fetch then | ||
| 145 | if opts.branch then | ||
| 146 | rockspec.source.branch = opts.branch | ||
| 147 | end | ||
| 148 | local ok, source_dir, errcode = fetch.fetch_sources(rockspec, true) | ||
| 149 | if not ok then | ||
| 150 | return nil, source_dir, errcode | ||
| 151 | end | ||
| 152 | local err | ||
| 153 | ok, err = fs.change_dir(source_dir) | ||
| 154 | if not ok then | ||
| 155 | return nil, err | ||
| 156 | end | ||
| 157 | elseif rockspec.source.file then | ||
| 158 | local ok, err = fs.unpack_archive(rockspec.source.file) | ||
| 159 | if not ok then | ||
| 160 | return nil, err | ||
| 161 | end | ||
| 162 | end | ||
| 163 | fs.change_dir(rockspec.source.dir) | ||
| 164 | return true | ||
| 165 | end | ||
| 166 | |||
| 167 | local function prepare_install_dirs(name, version) | ||
| 168 | local dirs = { | ||
| 169 | lua = { name = path.lua_dir(name, version), is_module_path = true, perms = "read" }, | ||
| 170 | lib = { name = path.lib_dir(name, version), is_module_path = true, perms = "exec" }, | ||
| 171 | bin = { name = path.bin_dir(name, version), is_module_path = false, perms = "exec" }, | ||
| 172 | conf = { name = path.conf_dir(name, version), is_module_path = false, perms = "read" }, | ||
| 173 | } | ||
| 174 | |||
| 175 | for _, d in pairs(dirs) do | ||
| 176 | local ok, err = fs.make_dir(d.name) | ||
| 177 | if not ok then | ||
| 178 | return nil, err | ||
| 179 | end | ||
| 180 | end | ||
| 181 | |||
| 182 | return dirs | ||
| 183 | end | ||
| 184 | |||
| 185 | local function run_build_driver(rockspec) | ||
| 186 | local btype = rockspec.build.type | ||
| 187 | if btype == "none" then | ||
| 188 | return true | ||
| 189 | end | ||
| 190 | -- Temporary compatibility | ||
| 191 | if btype == "module" then | ||
| 192 | util.printout("Do not use 'module' as a build type. Use 'builtin' instead.") | ||
| 193 | btype = "builtin" | ||
| 194 | rockspec.build.type = btype | ||
| 195 | end | ||
| 196 | if cfg.accepted_build_types and not fun.contains(cfg.accepted_build_types, btype) then | ||
| 197 | return nil, "This rockspec uses the '"..btype.."' build type, which is blocked by the 'accepted_build_types' setting in your LuaRocks configuration." | ||
| 198 | end | ||
| 199 | local pok, driver = pcall(require, "luarocks.build." .. btype) | ||
| 200 | if not pok or type(driver) ~= "table" then | ||
| 201 | return nil, "Failed initializing build back-end for build type '"..btype.."': "..driver | ||
| 202 | end | ||
| 203 | local ok, err = driver.run(rockspec) | ||
| 204 | if not ok then | ||
| 205 | return nil, "Build error: " .. err | ||
| 206 | end | ||
| 207 | return true | ||
| 208 | end | ||
| 209 | |||
| 210 | local install_files | ||
| 211 | do | ||
| 212 | --- Install files to a given location. | ||
| 213 | -- Takes a table where the array part is a list of filenames to be copied. | ||
| 214 | -- In the hash part, other keys, if is_module_path is set, are identifiers | ||
| 215 | -- in Lua module format, to indicate which subdirectory the file should be | ||
| 216 | -- copied to. For example, install_files({["foo.bar"] = "src/bar.lua"}, "boo") | ||
| 217 | -- will copy src/bar.lua to boo/foo. | ||
| 218 | -- @param files table or nil: A table containing a list of files to copy in | ||
| 219 | -- the format described above. If nil is passed, this function is a no-op. | ||
| 220 | -- Directories should be delimited by forward slashes as in internet URLs. | ||
| 221 | -- @param location string: The base directory files should be copied to. | ||
| 222 | -- @param is_module_path boolean: True if string keys in files should be | ||
| 223 | -- interpreted as dotted module paths. | ||
| 224 | -- @param perms string ("read" or "exec"): Permissions of the newly created | ||
| 225 | -- files installed. | ||
| 226 | -- Directories are always created with the default permissions. | ||
| 227 | -- @return boolean or (nil, string): True if succeeded or | ||
| 228 | -- nil and an error message. | ||
| 229 | local function install_to(files, location, is_module_path, perms) | ||
| 230 | assert(type(files) == "table" or not files) | ||
| 231 | assert(type(location) == "string") | ||
| 232 | if not files then | ||
| 233 | return true | ||
| 234 | end | ||
| 35 | for k, file in pairs(files) do | 235 | for k, file in pairs(files) do |
| 36 | local dest = location | 236 | local dest = location |
| 37 | local filename = dir.base_name(file) | 237 | local filename = dir.base_name(file) |
| @@ -60,88 +260,76 @@ local function install_files(files, location, is_module_path, perms) | |||
| 60 | return nil, "Failed copying "..file | 260 | return nil, "Failed copying "..file |
| 61 | end | 261 | end |
| 62 | end | 262 | end |
| 263 | return true | ||
| 63 | end | 264 | end |
| 64 | return true | ||
| 65 | end | ||
| 66 | 265 | ||
| 67 | --- Write to the current directory the contents of a table, | 266 | local function install_default_docs(name, version) |
| 68 | -- where each key is a file name and its value is the file content. | 267 | local patterns = { "readme", "license", "copying", ".*%.md" } |
| 69 | -- @param files table: The table of files to be written. | 268 | local dest = dir.path(path.install_dir(name, version), "doc") |
| 70 | local function extract_from_rockspec(files) | 269 | local has_dir = false |
| 71 | for name, content in pairs(files) do | 270 | for file in fs.dir() do |
| 72 | local fd = io.open(dir.path(fs.current_dir(), name), "w+") | 271 | for _, pattern in ipairs(patterns) do |
| 73 | fd:write(content) | 272 | if file:lower():match("^"..pattern) then |
| 74 | fd:close() | 273 | if not has_dir then |
| 274 | fs.make_dir(dest) | ||
| 275 | has_dir = true | ||
| 276 | end | ||
| 277 | fs.copy(file, dest, "read") | ||
| 278 | break | ||
| 279 | end | ||
| 280 | end | ||
| 281 | end | ||
| 75 | end | 282 | end |
| 76 | end | ||
| 77 | 283 | ||
| 78 | --- Applies patches inlined in the build.patches section | 284 | install_files = function(rockspec, dirs) |
| 79 | -- and extracts files inlined in the build.extra_files section | 285 | local name, version = rockspec.name, rockspec.version |
| 80 | -- of a rockspec. | 286 | |
| 81 | -- @param rockspec table: A rockspec table. | 287 | if rockspec.build.install then |
| 82 | -- @return boolean or (nil, string): True if succeeded or | 288 | for k, d in pairs(dirs) do |
| 83 | -- nil and an error message. | 289 | local ok, err = install_to(rockspec.build.install[k], d.name, d.is_module_path, d.perms) |
| 84 | function build.apply_patches(rockspec) | 290 | if not ok then return nil, err end |
| 85 | assert(type(rockspec) == "table") | ||
| 86 | |||
| 87 | local build_spec = rockspec.build | ||
| 88 | if build_spec.extra_files then | ||
| 89 | extract_from_rockspec(build_spec.extra_files) | ||
| 90 | end | ||
| 91 | if build_spec.patches then | ||
| 92 | extract_from_rockspec(build_spec.patches) | ||
| 93 | for patch, patchdata in util.sortedpairs(build_spec.patches) do | ||
| 94 | util.printout("Applying patch "..patch.."...") | ||
| 95 | local create_delete = rockspec:format_is_at_least("3.0") | ||
| 96 | local ok, err = fs.apply_patch(tostring(patch), patchdata, create_delete) | ||
| 97 | if not ok then | ||
| 98 | return nil, "Failed applying patch "..patch | ||
| 99 | end | 291 | end |
| 100 | end | 292 | end |
| 101 | end | ||
| 102 | return true | ||
| 103 | end | ||
| 104 | 293 | ||
| 105 | local function install_default_docs(name, version) | 294 | local copy_directories = rockspec.build.copy_directories |
| 106 | local patterns = { "readme", "license", "copying", ".*%.md" } | 295 | local copying_default = false |
| 107 | local dest = dir.path(path.install_dir(name, version), "doc") | 296 | if not copy_directories then |
| 108 | local has_dir = false | 297 | copy_directories = {"doc"} |
| 109 | for file in fs.dir() do | 298 | copying_default = true |
| 110 | for _, pattern in ipairs(patterns) do | 299 | end |
| 111 | if file:lower():match("^"..pattern) then | 300 | |
| 112 | if not has_dir then | 301 | local any_docs = false |
| 113 | fs.make_dir(dest) | 302 | for _, copy_dir in pairs(copy_directories) do |
| 114 | has_dir = true | 303 | if fs.is_dir(copy_dir) then |
| 304 | local dest = dir.path(path.install_dir(name, version), copy_dir) | ||
| 305 | fs.make_dir(dest) | ||
| 306 | fs.copy_contents(copy_dir, dest) | ||
| 307 | any_docs = true | ||
| 308 | else | ||
| 309 | if not copying_default then | ||
| 310 | return nil, "Directory '"..copy_dir.."' not found" | ||
| 115 | end | 311 | end |
| 116 | fs.copy(file, dest, "read") | ||
| 117 | break | ||
| 118 | end | 312 | end |
| 119 | end | 313 | end |
| 314 | if not any_docs then | ||
| 315 | install_default_docs(name, version) | ||
| 316 | end | ||
| 317 | |||
| 318 | return true | ||
| 120 | end | 319 | end |
| 121 | end | 320 | end |
| 122 | 321 | ||
| 123 | local function check_macosx_deployment_target(rockspec) | 322 | local function write_rock_dir_files(rockspec, opts) |
| 124 | local target = rockspec.build.macosx_deployment_target | 323 | local name, version = rockspec.name, rockspec.version |
| 125 | local function minor(version) | 324 | |
| 126 | return tonumber(version and version:match("^[^.]+%.([^.]+)")) | 325 | fs.copy(rockspec.local_abs_filename, path.rockspec_file(name, version), "read") |
| 127 | end | 326 | |
| 128 | local function patch_variable(var, target) | 327 | local ok, err = writer.make_rock_manifest(name, version) |
| 129 | if rockspec.variables[var]:match("MACOSX_DEPLOYMENT_TARGET") then | 328 | if not ok then return nil, err end |
| 130 | rockspec.variables[var] = (rockspec.variables[var]):gsub("MACOSX_DEPLOYMENT_TARGET=[^ ]*", "MACOSX_DEPLOYMENT_TARGET="..target) | 329 | |
| 131 | else | 330 | ok, err = writer.make_namespace_file(name, version, opts.namespace) |
| 132 | rockspec.variables[var] = "env MACOSX_DEPLOYMENT_TARGET="..target.." "..rockspec.variables[var] | 331 | if not ok then return nil, err end |
| 133 | end | 332 | |
| 134 | end | ||
| 135 | if cfg.platforms.macosx and rockspec:format_is_at_least("3.0") and target then | ||
| 136 | local version = util.popen_read("sw_vers -productVersion") | ||
| 137 | local versionminor = minor(version) | ||
| 138 | local targetminor = minor(target) | ||
| 139 | if targetminor > versionminor then | ||
| 140 | return nil, ("This rock requires Mac OSX 10.%d, and you are running 10.%d."):format(targetminor, versionminor) | ||
| 141 | end | ||
| 142 | patch_variable("CC", target) | ||
| 143 | patch_variable("LD", target) | ||
| 144 | end | ||
| 145 | return true | 333 | return true |
| 146 | end | 334 | end |
| 147 | 335 | ||
| @@ -157,18 +345,14 @@ end | |||
| 157 | -- "none" for no trees. | 345 | -- "none" for no trees. |
| 158 | -- @param build_only_deps boolean: true to build the listed dependencies only. | 346 | -- @param build_only_deps boolean: true to build the listed dependencies only. |
| 159 | -- @param namespace string?: a namespace for the rockspec | 347 | -- @param namespace string?: a namespace for the rockspec |
| 348 | -- @param branch string?: a forced branch to use | ||
| 160 | -- @return (string, string) or (nil, string, [string]): Name and version of | 349 | -- @return (string, string) or (nil, string, [string]): Name and version of |
| 161 | -- installed rock if succeeded or nil and an error message followed by an error code. | 350 | -- installed rock if succeeded or nil and an error message followed by an error code. |
| 162 | function build.build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_mode, build_only_deps, namespace) | 351 | function build.build_rockspec(rockspec, opts) |
| 163 | assert(type(rockspec_file) == "string") | 352 | assert(rockspec:type() == "rockspec") |
| 164 | assert(type(need_to_fetch) == "boolean") | 353 | assert(opts:type() == "build.opts") |
| 165 | assert(type(namespace) == "string" or not namespace) | ||
| 166 | 354 | ||
| 167 | local ok | 355 | if not rockspec.build then |
| 168 | local rockspec, err, errcode = fetch.load_rockspec(rockspec_file) | ||
| 169 | if err then | ||
| 170 | return nil, err, errcode | ||
| 171 | elseif not rockspec.build then | ||
| 172 | return nil, "Rockspec error: build table not specified" | 356 | return nil, "Rockspec error: build table not specified" |
| 173 | end | 357 | end |
| 174 | 358 | ||
| @@ -180,175 +364,65 @@ function build.build_rockspec(rockspec_file, need_to_fetch, minimal_mode, deps_m | |||
| 180 | end | 364 | end |
| 181 | end | 365 | end |
| 182 | 366 | ||
| 183 | if not build_only_deps then | 367 | local ok, err = process_dependencies(rockspec, opts) |
| 184 | local ok, err, errcode = deps.check_external_deps(rockspec, "build") | 368 | if not ok then return nil, err end |
| 185 | if err then | ||
| 186 | return nil, err, errcode | ||
| 187 | end | ||
| 188 | end | ||
| 189 | |||
| 190 | if deps_mode == "none" then | ||
| 191 | util.warning("skipping dependency checks.") | ||
| 192 | else | ||
| 193 | if not build_only_deps then | ||
| 194 | if next(rockspec.build_dependencies) then | ||
| 195 | local ok, err, errcode = deps.fulfill_dependencies(rockspec, "build_dependencies", deps_mode) | ||
| 196 | if err then | ||
| 197 | return nil, err, errcode | ||
| 198 | end | ||
| 199 | end | ||
| 200 | end | ||
| 201 | |||
| 202 | local ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", deps_mode) | ||
| 203 | if err then | ||
| 204 | return nil, err, errcode | ||
| 205 | end | ||
| 206 | end | ||
| 207 | 369 | ||
| 208 | local name, version = rockspec.name, rockspec.version | 370 | local name, version = rockspec.name, rockspec.version |
| 209 | if build_only_deps then | 371 | if opts.build_only_deps then |
| 210 | util.printout("Stopping after installing dependencies for " ..name.." "..version) | ||
| 211 | util.printout() | ||
| 212 | return name, version | 372 | return name, version |
| 213 | end | 373 | end |
| 214 | 374 | ||
| 215 | if repos.is_installed(name, version) then | 375 | if repos.is_installed(name, version) then |
| 216 | repos.delete_version(name, version, deps_mode) | 376 | repos.delete_version(name, version, opts.deps_mode) |
| 217 | end | 377 | end |
| 218 | 378 | ||
| 219 | if not minimal_mode then | 379 | ok, err = fetch_and_change_to_source_dir(rockspec, opts) |
| 220 | local source_dir | 380 | if not ok then return nil, err end |
| 221 | if need_to_fetch then | ||
| 222 | ok, source_dir, errcode = fetch.fetch_sources(rockspec, true) | ||
| 223 | if not ok then | ||
| 224 | return nil, source_dir, errcode | ||
| 225 | end | ||
| 226 | local ok, err = fs.change_dir(source_dir) | ||
| 227 | if not ok then return nil, err end | ||
| 228 | elseif rockspec.source.file then | ||
| 229 | local ok, err = fs.unpack_archive(rockspec.source.file) | ||
| 230 | if not ok then | ||
| 231 | return nil, err | ||
| 232 | end | ||
| 233 | end | ||
| 234 | fs.change_dir(rockspec.source.dir) | ||
| 235 | end | ||
| 236 | 381 | ||
| 237 | local dirs = { | 382 | local dirs, err = prepare_install_dirs(name, version) |
| 238 | lua = { name = path.lua_dir(name, version), is_module_path = true, perms = "read" }, | 383 | if not dirs then return nil, err end |
| 239 | lib = { name = path.lib_dir(name, version), is_module_path = true, perms = "exec" }, | ||
| 240 | conf = { name = path.conf_dir(name, version), is_module_path = false, perms = "read" }, | ||
| 241 | bin = { name = path.bin_dir(name, version), is_module_path = false, perms = "exec" }, | ||
| 242 | } | ||
| 243 | 384 | ||
| 244 | for _, d in pairs(dirs) do | ||
| 245 | local ok, err = fs.make_dir(d.name) | ||
| 246 | if not ok then return nil, err end | ||
| 247 | end | ||
| 248 | local rollback = util.schedule_function(function() | 385 | local rollback = util.schedule_function(function() |
| 249 | fs.delete(path.install_dir(name, version)) | 386 | fs.delete(path.install_dir(name, version)) |
| 250 | fs.remove_dir_if_empty(path.versions_dir(name)) | 387 | fs.remove_dir_if_empty(path.versions_dir(name)) |
| 251 | end) | 388 | end) |
| 252 | 389 | ||
| 253 | local build_spec = rockspec.build | 390 | if not opts.minimal_mode then |
| 254 | 391 | local ok, err = build.apply_patches(rockspec) | |
| 255 | if not minimal_mode then | 392 | if not ok then return nil, err end |
| 256 | ok, err = build.apply_patches(rockspec) | ||
| 257 | if err then | ||
| 258 | return nil, err | ||
| 259 | end | ||
| 260 | end | 393 | end |
| 261 | 394 | ||
| 262 | ok, err = check_macosx_deployment_target(rockspec) | 395 | ok, err = check_macosx_deployment_target(rockspec) |
| 263 | if not ok then | 396 | if not ok then return nil, err end |
| 264 | return nil, err | ||
| 265 | end | ||
| 266 | |||
| 267 | if build_spec.type ~= "none" then | ||
| 268 | |||
| 269 | -- Temporary compatibility | ||
| 270 | if build_spec.type == "module" then | ||
| 271 | util.printout("Do not use 'module' as a build type. Use 'builtin' instead.") | ||
| 272 | build_spec.type = "builtin" | ||
| 273 | end | ||
| 274 | |||
| 275 | if cfg.accepted_build_types and fun.contains(cfg.accepted_build_types, build_spec.type) then | ||
| 276 | return nil, "This rockspec uses the '"..build_spec.type.."' build type, which is blocked by the 'accepted_build_types' setting in your LuaRocks configuration." | ||
| 277 | end | ||
| 278 | |||
| 279 | local build_type | ||
| 280 | ok, build_type = pcall(require, "luarocks.build." .. build_spec.type) | ||
| 281 | if not ok or not type(build_type) == "table" then | ||
| 282 | return nil, "Failed initializing build back-end for build type '"..build_spec.type.."': "..build_type | ||
| 283 | end | ||
| 284 | |||
| 285 | ok, err = build_type.run(rockspec) | ||
| 286 | if not ok then | ||
| 287 | return nil, "Build error: " .. err | ||
| 288 | end | ||
| 289 | end | ||
| 290 | |||
| 291 | if build_spec.install then | ||
| 292 | for id, install_dir in pairs(dirs) do | ||
| 293 | ok, err = install_files(build_spec.install[id], install_dir.name, install_dir.is_module_path, install_dir.perms) | ||
| 294 | if not ok then | ||
| 295 | return nil, err | ||
| 296 | end | ||
| 297 | end | ||
| 298 | end | ||
| 299 | 397 | ||
| 300 | local copy_directories = build_spec.copy_directories | 398 | ok, err = run_build_driver(rockspec) |
| 301 | local copying_default = false | 399 | if not ok then return nil, err end |
| 302 | if not copy_directories then | ||
| 303 | copy_directories = {"doc"} | ||
| 304 | copying_default = true | ||
| 305 | end | ||
| 306 | |||
| 307 | local any_docs = false | ||
| 308 | for _, copy_dir in pairs(copy_directories) do | ||
| 309 | if fs.is_dir(copy_dir) then | ||
| 310 | local dest = dir.path(path.install_dir(name, version), copy_dir) | ||
| 311 | fs.make_dir(dest) | ||
| 312 | fs.copy_contents(copy_dir, dest) | ||
| 313 | any_docs = true | ||
| 314 | else | ||
| 315 | if not copying_default then | ||
| 316 | return nil, "Directory '"..copy_dir.."' not found" | ||
| 317 | end | ||
| 318 | end | ||
| 319 | end | ||
| 320 | 400 | ||
| 321 | if not any_docs then | 401 | ok, err = install_files(rockspec, dirs) |
| 322 | install_default_docs(name, version) | 402 | if not ok then return nil, err end |
| 323 | end | ||
| 324 | 403 | ||
| 325 | for _, d in pairs(dirs) do | 404 | for _, d in pairs(dirs) do |
| 326 | fs.remove_dir_if_empty(d.name) | 405 | fs.remove_dir_if_empty(d.name) |
| 327 | end | 406 | end |
| 328 | 407 | ||
| 329 | fs.pop_dir() | 408 | fs.pop_dir() |
| 330 | 409 | if opts.need_to_fetch then | |
| 331 | fs.copy(rockspec.local_filename, path.rockspec_file(name, version), "read") | ||
| 332 | if need_to_fetch then | ||
| 333 | fs.pop_dir() | 410 | fs.pop_dir() |
| 334 | end | 411 | end |
| 335 | 412 | ||
| 336 | ok, err = writer.make_rock_manifest(name, version) | 413 | ok, err = write_rock_dir_files(rockspec, opts) |
| 337 | if err then return nil, err end | 414 | if not ok then return nil, err end |
| 338 | |||
| 339 | ok, err = writer.make_namespace_file(name, version, namespace) | ||
| 340 | if err then return nil, err end | ||
| 341 | 415 | ||
| 342 | ok, err = repos.deploy_files(name, version, repos.should_wrap_bin_scripts(rockspec), deps_mode) | 416 | ok, err = repos.deploy_files(name, version, repos.should_wrap_bin_scripts(rockspec), opts.deps_mode) |
| 343 | if err then return nil, err end | 417 | if not ok then return nil, err end |
| 344 | 418 | ||
| 345 | util.remove_scheduled_function(rollback) | 419 | util.remove_scheduled_function(rollback) |
| 346 | rollback = util.schedule_function(function() | 420 | rollback = util.schedule_function(function() |
| 347 | repos.delete_version(name, version, deps_mode) | 421 | repos.delete_version(name, version, opts.deps_mode) |
| 348 | end) | 422 | end) |
| 349 | 423 | ||
| 350 | ok, err = repos.run_hook(rockspec, "post_install") | 424 | ok, err = repos.run_hook(rockspec, "post_install") |
| 351 | if err then return nil, err end | 425 | if not ok then return nil, err end |
| 352 | 426 | ||
| 353 | util.announce_install(rockspec) | 427 | util.announce_install(rockspec) |
| 354 | util.remove_scheduled_function(rollback) | 428 | util.remove_scheduled_function(rollback) |
diff --git a/src/luarocks/build/builtin.lua b/src/luarocks/build/builtin.lua index e8b0943d..41cc31b0 100644 --- a/src/luarocks/build/builtin.lua +++ b/src/luarocks/build/builtin.lua | |||
| @@ -23,7 +23,7 @@ end | |||
| 23 | -- @return boolean or (nil, string): true if no errors ocurred, | 23 | -- @return boolean or (nil, string): true if no errors ocurred, |
| 24 | -- nil and an error message otherwise. | 24 | -- nil and an error message otherwise. |
| 25 | function builtin.run(rockspec) | 25 | function builtin.run(rockspec) |
| 26 | assert(type(rockspec) == "table") | 26 | assert(rockspec:type() == "rockspec") |
| 27 | local compile_object, compile_library, compile_static_library | 27 | local compile_object, compile_library, compile_static_library |
| 28 | 28 | ||
| 29 | local build = rockspec.build | 29 | local build = rockspec.build |
diff --git a/src/luarocks/build/cmake.lua b/src/luarocks/build/cmake.lua index 8ee6b6b2..e5db695c 100644 --- a/src/luarocks/build/cmake.lua +++ b/src/luarocks/build/cmake.lua | |||
| @@ -11,7 +11,7 @@ local cfg = require("luarocks.core.cfg") | |||
| 11 | -- @return boolean or (nil, string): true if no errors ocurred, | 11 | -- @return boolean or (nil, string): true if no errors ocurred, |
| 12 | -- nil and an error message otherwise. | 12 | -- nil and an error message otherwise. |
| 13 | function cmake.run(rockspec) | 13 | function cmake.run(rockspec) |
| 14 | assert(type(rockspec) == "table") | 14 | assert(rockspec:type() == "rockspec") |
| 15 | local build = rockspec.build | 15 | local build = rockspec.build |
| 16 | local variables = build.variables or {} | 16 | local variables = build.variables or {} |
| 17 | 17 | ||
diff --git a/src/luarocks/build/command.lua b/src/luarocks/build/command.lua index 62dbc282..23d6d80d 100644 --- a/src/luarocks/build/command.lua +++ b/src/luarocks/build/command.lua | |||
| @@ -10,7 +10,7 @@ local util = require("luarocks.util") | |||
| 10 | -- @return boolean or (nil, string): true if no errors ocurred, | 10 | -- @return boolean or (nil, string): true if no errors ocurred, |
| 11 | -- nil and an error message otherwise. | 11 | -- nil and an error message otherwise. |
| 12 | function command.run(rockspec) | 12 | function command.run(rockspec) |
| 13 | assert(type(rockspec) == "table") | 13 | assert(rockspec:type() == "rockspec") |
| 14 | 14 | ||
| 15 | local build = rockspec.build | 15 | local build = rockspec.build |
| 16 | 16 | ||
diff --git a/src/luarocks/build/make.lua b/src/luarocks/build/make.lua index ded015b7..22b8628b 100644 --- a/src/luarocks/build/make.lua +++ b/src/luarocks/build/make.lua | |||
| @@ -39,7 +39,7 @@ end | |||
| 39 | -- @return boolean or (nil, string): true if no errors ocurred, | 39 | -- @return boolean or (nil, string): true if no errors ocurred, |
| 40 | -- nil and an error message otherwise. | 40 | -- nil and an error message otherwise. |
| 41 | function make.run(rockspec) | 41 | function make.run(rockspec) |
| 42 | assert(type(rockspec) == "table") | 42 | assert(rockspec:type() == "rockspec") |
| 43 | 43 | ||
| 44 | local build = rockspec.build | 44 | local build = rockspec.build |
| 45 | 45 | ||
diff --git a/src/luarocks/cmd/build.lua b/src/luarocks/cmd/build.lua index 0c8c4d47..08a05296 100644 --- a/src/luarocks/cmd/build.lua +++ b/src/luarocks/cmd/build.lua | |||
| @@ -41,7 +41,7 @@ or the name of a rock to be fetched from a repository. | |||
| 41 | ]]..util.deps_mode_help() | 41 | ]]..util.deps_mode_help() |
| 42 | 42 | ||
| 43 | --- Build and install a rock. | 43 | --- Build and install a rock. |
| 44 | -- @param rock_file string: local or remote filename of a rock. | 44 | -- @param rock_filename string: local or remote filename of a rock. |
| 45 | -- @param need_to_fetch boolean: true if sources need to be fetched, | 45 | -- @param need_to_fetch boolean: true if sources need to be fetched, |
| 46 | -- false if the rockspec was obtained from inside a source rock. | 46 | -- false if the rockspec was obtained from inside a source rock. |
| 47 | -- @param deps_mode: string: Which trees to check dependencies for: | 47 | -- @param deps_mode: string: Which trees to check dependencies for: |
| @@ -51,42 +51,65 @@ or the name of a rock to be fetched from a repository. | |||
| 51 | -- @param namespace string?: an optional namespace | 51 | -- @param namespace string?: an optional namespace |
| 52 | -- @return boolean or (nil, string, [string]): True if build was successful, | 52 | -- @return boolean or (nil, string, [string]): True if build was successful, |
| 53 | -- or false and an error message and an optional error code. | 53 | -- or false and an error message and an optional error code. |
| 54 | local function build_rock(rock_file, need_to_fetch, deps_mode, build_only_deps, namespace) | 54 | local function build_rock(rock_filename, opts) |
| 55 | assert(type(rock_file) == "string") | 55 | assert(type(rock_filename) == "string") |
| 56 | assert(type(need_to_fetch) == "boolean") | 56 | assert(opts:type() == "build.opts") |
| 57 | 57 | ||
| 58 | local ok, err, errcode | 58 | local ok, err, errcode |
| 59 | |||
| 59 | local unpack_dir | 60 | local unpack_dir |
| 60 | unpack_dir, err, errcode = fetch.fetch_and_unpack_rock(rock_file) | 61 | unpack_dir, err, errcode = fetch.fetch_and_unpack_rock(rock_filename) |
| 61 | if not unpack_dir then | 62 | if not unpack_dir then |
| 62 | return nil, err, errcode | 63 | return nil, err, errcode |
| 63 | end | 64 | end |
| 64 | local rockspec_file = path.rockspec_name_from_rock(rock_file) | 65 | |
| 66 | local rockspec_filename = path.rockspec_name_from_rock(rock_filename) | ||
| 67 | |||
| 65 | ok, err = fs.change_dir(unpack_dir) | 68 | ok, err = fs.change_dir(unpack_dir) |
| 66 | if not ok then return nil, err end | 69 | if not ok then return nil, err end |
| 67 | ok, err, errcode = build.build_rockspec(rockspec_file, need_to_fetch, false, deps_mode, build_only_deps, namespace) | 70 | |
| 71 | local rockspec | ||
| 72 | rockspec, err, errcode = fetch.load_rockspec(rockspec_filename) | ||
| 73 | if not rockspec then | ||
| 74 | return nil, err, errcode | ||
| 75 | end | ||
| 76 | |||
| 77 | ok, err, errcode = build.build_rockspec(rockspec, opts) | ||
| 78 | |||
| 68 | fs.pop_dir() | 79 | fs.pop_dir() |
| 69 | return ok, err, errcode | 80 | return ok, err, errcode |
| 70 | end | 81 | end |
| 71 | 82 | ||
| 72 | local function build_file(filename, namespace, deps_mode, build_only_deps) | 83 | local function do_build(ns_name, version, opts) |
| 73 | if filename:match("%.rockspec$") then | 84 | assert(type(ns_name) == "string") |
| 74 | return build.build_rockspec(filename, true, false, deps_mode, build_only_deps, namespace) | 85 | assert(version == nil or type(version) == "string") |
| 75 | elseif filename:match("%.src%.rock$") then | 86 | assert(opts:type() == "build.opts") |
| 76 | return build_rock(filename, false, deps_mode, build_only_deps, namespace) | ||
| 77 | elseif filename:match("%.all%.rock$") then | ||
| 78 | return build_rock(filename, true, deps_mode, build_only_deps, namespace) | ||
| 79 | elseif filename:match("%.rock$") then | ||
| 80 | return build_rock(filename, true, deps_mode, build_only_deps, namespace) | ||
| 81 | end | ||
| 82 | end | ||
| 83 | 87 | ||
| 84 | local function do_build(name, version, namespace, deps_mode, build_only_deps) | 88 | local url, err |
| 85 | if name:match("%.rockspec$") or name:match("%.rock$") then | 89 | if ns_name:match("%.rockspec$") or ns_name:match("%.rock$") then |
| 86 | return build_file(name, namespace, deps_mode, build_only_deps) | 90 | url = ns_name |
| 87 | else | 91 | else |
| 88 | return search.act_on_src_or_rockspec(build_file, name, version, deps_mode, build_only_deps) | 92 | url, err = search.find_src_or_rockspec(ns_name, version) |
| 93 | if not url then | ||
| 94 | return nil, err | ||
| 95 | end | ||
| 96 | local _, namespace = util.split_namespace(ns_name) | ||
| 97 | opts.namespace = namespace | ||
| 98 | end | ||
| 99 | |||
| 100 | if url:match("%.rockspec$") then | ||
| 101 | local rockspec, err, errcode = fetch.load_rockspec(url) | ||
| 102 | if not rockspec then | ||
| 103 | return nil, err, errcode | ||
| 104 | end | ||
| 105 | return build.build_rockspec(rockspec, opts) | ||
| 106 | end | ||
| 107 | |||
| 108 | if url:match("%.src%.rock$") then | ||
| 109 | opts.need_to_fetch = false | ||
| 89 | end | 110 | end |
| 111 | |||
| 112 | return build_rock(url, opts) | ||
| 90 | end | 113 | end |
| 91 | 114 | ||
| 92 | --- Driver function for "build" command. | 115 | --- Driver function for "build" command. |
| @@ -106,28 +129,46 @@ function cmd_build.command(flags, name, version) | |||
| 106 | end | 129 | end |
| 107 | 130 | ||
| 108 | name = util.adjust_name_and_namespace(name, flags) | 131 | name = util.adjust_name_and_namespace(name, flags) |
| 109 | local deps_mode = deps.get_deps_mode(flags) | 132 | |
| 110 | local namespace = flags["namespace"] | 133 | local opts = build.opts({ |
| 111 | local build_only_deps = flags["only-deps"] | 134 | need_to_fetch = true, |
| 135 | minimal_mode = false, | ||
| 136 | deps_mode = deps.get_deps_mode(flags), | ||
| 137 | build_only_deps = not not flags["only-deps"], | ||
| 138 | namespace = flags["namespace"], | ||
| 139 | branch = not not flags["branch"], | ||
| 140 | }) | ||
| 112 | 141 | ||
| 113 | if flags["pack-binary-rock"] then | 142 | if flags["pack-binary-rock"] then |
| 114 | return pack.pack_binary_rock(name, version, function() return do_build(name, version, namespace, deps_mode) end) | 143 | return pack.pack_binary_rock(name, version, function() |
| 115 | else | 144 | opts.build_only_deps = false |
| 116 | local ok, err = fs.check_command_permissions(flags) | 145 | return do_build(name, version, opts) |
| 117 | if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end | 146 | end) |
| 147 | end | ||
| 148 | |||
| 149 | local ok, err = fs.check_command_permissions(flags) | ||
| 150 | if not ok then | ||
| 151 | return nil, err, cfg.errorcodes.PERMISSIONDENIED | ||
| 152 | end | ||
| 118 | 153 | ||
| 119 | ok, err = do_build(name, version, namespace, deps_mode, build_only_deps) | 154 | ok, err = do_build(name, version, opts) |
| 120 | if not ok then return nil, err end | 155 | if not ok then return nil, err end |
| 121 | name, version = ok, err | 156 | name, version = ok, err |
| 122 | 157 | ||
| 123 | if (not build_only_deps) and (not flags["keep"]) and not cfg.keep_other_versions then | 158 | if opts.build_only_deps then |
| 159 | util.printout("Stopping after installing dependencies for " ..name.." "..version) | ||
| 160 | util.printout() | ||
| 161 | else | ||
| 162 | if (not flags["keep"]) and not cfg.keep_other_versions then | ||
| 124 | local ok, err = remove.remove_other_versions(name, version, flags["force"], flags["force-fast"]) | 163 | local ok, err = remove.remove_other_versions(name, version, flags["force"], flags["force-fast"]) |
| 125 | if not ok then util.printerr(err) end | 164 | if not ok then |
| 165 | util.printerr(err) | ||
| 166 | end | ||
| 126 | end | 167 | end |
| 127 | |||
| 128 | writer.check_dependencies(nil, deps.get_deps_mode(flags)) | ||
| 129 | return name, version | ||
| 130 | end | 168 | end |
| 169 | |||
| 170 | writer.check_dependencies(nil, deps.get_deps_mode(flags)) | ||
| 171 | return name, version | ||
| 131 | end | 172 | end |
| 132 | 173 | ||
| 133 | return cmd_build | 174 | return cmd_build |
diff --git a/src/luarocks/cmd/make.lua b/src/luarocks/cmd/make.lua index 850da6f4..caf64721 100644 --- a/src/luarocks/cmd/make.lua +++ b/src/luarocks/cmd/make.lua | |||
| @@ -53,30 +53,44 @@ only dependencies of the rockspec (see `luarocks help install`). | |||
| 53 | -- @param name string: A local rockspec. | 53 | -- @param name string: A local rockspec. |
| 54 | -- @return boolean or (nil, string, exitcode): True if build was successful; nil and an | 54 | -- @return boolean or (nil, string, exitcode): True if build was successful; nil and an |
| 55 | -- error message otherwise. exitcode is optionally returned. | 55 | -- error message otherwise. exitcode is optionally returned. |
| 56 | function make.command(flags, rockspec) | 56 | function make.command(flags, rockspec_filename) |
| 57 | assert(type(rockspec) == "string" or not rockspec) | 57 | assert(type(rockspec_filename) == "string" or not rockspec_filename) |
| 58 | 58 | ||
| 59 | if not rockspec then | 59 | if not rockspec_filename then |
| 60 | local err | 60 | local err |
| 61 | rockspec, err = util.get_default_rockspec() | 61 | rockspec_filename, err = util.get_default_rockspec() |
| 62 | if not rockspec then | 62 | if not rockspec_filename then |
| 63 | return nil, err | 63 | return nil, err |
| 64 | end | 64 | end |
| 65 | end | 65 | end |
| 66 | if not rockspec:match("rockspec$") then | 66 | if not rockspec_filename:match("rockspec$") then |
| 67 | return nil, "Invalid argument: 'make' takes a rockspec as a parameter. "..util.see_help("make") | 67 | return nil, "Invalid argument: 'make' takes a rockspec as a parameter. "..util.see_help("make") |
| 68 | end | 68 | end |
| 69 | |||
| 70 | local rockspec, err, errcode = fetch.load_rockspec(rockspec_filename) | ||
| 71 | if not rockspec then | ||
| 72 | return nil, err | ||
| 73 | end | ||
| 74 | |||
| 75 | local name = util.adjust_name_and_namespace(rockspec.name, flags) | ||
| 76 | |||
| 77 | local opts = build.opts({ | ||
| 78 | need_to_fetch = false, | ||
| 79 | minimal_mode = true, | ||
| 80 | deps_mode = deps.get_deps_mode(flags), | ||
| 81 | build_only_deps = false, | ||
| 82 | namespace = flags["namespace"], | ||
| 83 | branch = not not flags["branch"], | ||
| 84 | }) | ||
| 69 | 85 | ||
| 70 | if flags["pack-binary-rock"] then | 86 | if flags["pack-binary-rock"] then |
| 71 | local rspec, err, errcode = fetch.load_rockspec(rockspec) | 87 | return pack.pack_binary_rock(name, rockspec.version, function() |
| 72 | if not rspec then | 88 | return build.build_rockspec(rockspec, opts) |
| 73 | return nil, err | 89 | end) |
| 74 | end | ||
| 75 | return pack.pack_binary_rock(rspec.name, rspec.version, function() return build.build_rockspec(rockspec, false, true, deps.get_deps_mode(flags)) end) | ||
| 76 | else | 90 | else |
| 77 | local ok, err = fs.check_command_permissions(flags) | 91 | local ok, err = fs.check_command_permissions(flags) |
| 78 | if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end | 92 | if not ok then return nil, err, cfg.errorcodes.PERMISSIONDENIED end |
| 79 | ok, err = build.build_rockspec(rockspec, false, true, deps.get_deps_mode(flags)) | 93 | ok, err = build.build_rockspec(rockspec, opts) |
| 80 | if not ok then return nil, err end | 94 | if not ok then return nil, err end |
| 81 | local name, version = ok, err | 95 | local name, version = ok, err |
| 82 | 96 | ||
diff --git a/src/luarocks/cmd/unpack.lua b/src/luarocks/cmd/unpack.lua index 3e512d5d..83dec7fe 100644 --- a/src/luarocks/cmd/unpack.lua +++ b/src/luarocks/cmd/unpack.lua | |||
| @@ -8,7 +8,7 @@ local fs = require("luarocks.fs") | |||
| 8 | local util = require("luarocks.util") | 8 | local util = require("luarocks.util") |
| 9 | local build = require("luarocks.build") | 9 | local build = require("luarocks.build") |
| 10 | local dir = require("luarocks.dir") | 10 | local dir = require("luarocks.dir") |
| 11 | local cfg = require("luarocks.core.cfg") | 11 | local search = require("luarocks.search") |
| 12 | 12 | ||
| 13 | unpack.help_summary = "Unpack the contents of a rock." | 13 | unpack.help_summary = "Unpack the contents of a rock." |
| 14 | unpack.help_arguments = "[--force] {<rock>|<name> [<version>]}" | 14 | unpack.help_arguments = "[--force] {<rock>|<name> [<version>]}" |
| @@ -92,7 +92,7 @@ end | |||
| 92 | -- @param file string: A rockspec or .rock URL. | 92 | -- @param file string: A rockspec or .rock URL. |
| 93 | -- @return boolean or (nil, string): true if successful or nil followed | 93 | -- @return boolean or (nil, string): true if successful or nil followed |
| 94 | -- by an error message. | 94 | -- by an error message. |
| 95 | local function run_unpacker(file, namespace, force) | 95 | local function run_unpacker(file, force) |
| 96 | assert(type(file) == "string") | 96 | assert(type(file) == "string") |
| 97 | 97 | ||
| 98 | local base_name = dir.base_name(file) | 98 | local base_name = dir.base_name(file) |
| @@ -126,7 +126,7 @@ local function run_unpacker(file, namespace, force) | |||
| 126 | end | 126 | end |
| 127 | if kind == "src" or kind == "rockspec" then | 127 | if kind == "src" or kind == "rockspec" then |
| 128 | if rockspec.source.dir ~= "." then | 128 | if rockspec.source.dir ~= "." then |
| 129 | local ok = fs.copy(rockspec.local_filename, rockspec.source.dir, "read") | 129 | local ok = fs.copy(rockspec.local_abs_filename, rockspec.source.dir, "read") |
| 130 | if not ok then | 130 | if not ok then |
| 131 | return nil, "Failed copying unpacked rockspec into unpacked source directory." | 131 | return nil, "Failed copying unpacked rockspec into unpacked source directory." |
| 132 | end | 132 | end |
| @@ -141,26 +141,31 @@ local function run_unpacker(file, namespace, force) | |||
| 141 | end | 141 | end |
| 142 | 142 | ||
| 143 | --- Driver function for the "unpack" command. | 143 | --- Driver function for the "unpack" command. |
| 144 | -- @param name string: may be a rock filename, for unpacking a | 144 | -- @param ns_name string: may be a rock filename, for unpacking a |
| 145 | -- rock file or the name of a rock to be fetched and unpacked. | 145 | -- rock file or the name of a rock to be fetched and unpacked. |
| 146 | -- @param version string or nil: if the name of a package is given, a | 146 | -- @param version string or nil: if the name of a package is given, a |
| 147 | -- version may also be passed. | 147 | -- version may also be passed. |
| 148 | -- @return boolean or (nil, string): true if successful or nil followed | 148 | -- @return boolean or (nil, string): true if successful or nil followed |
| 149 | -- by an error message. | 149 | -- by an error message. |
| 150 | function unpack.command(flags, name, version) | 150 | function unpack.command(flags, ns_name, version) |
| 151 | assert(type(version) == "string" or not version) | 151 | assert(type(version) == "string" or not version) |
| 152 | if type(name) ~= "string" then | 152 | if type(ns_name) ~= "string" then |
| 153 | return nil, "Argument missing. "..util.see_help("unpack") | 153 | return nil, "Argument missing. "..util.see_help("unpack") |
| 154 | end | 154 | end |
| 155 | 155 | ||
| 156 | name = util.adjust_name_and_namespace(name, flags) | 156 | ns_name = util.adjust_name_and_namespace(ns_name, flags) |
| 157 | 157 | ||
| 158 | if name:match(".*%.rock") or name:match(".*%.rockspec") then | 158 | local url, err |
| 159 | return run_unpacker(name, flags["namespace"], flags["force"]) | 159 | if ns_name:match(".*%.rock") or ns_name:match(".*%.rockspec") then |
| 160 | url = ns_name | ||
| 160 | else | 161 | else |
| 161 | local search = require("luarocks.search") | 162 | url, err = search.find_src_or_rockspec(ns_name, version) |
| 162 | return search.act_on_src_or_rockspec(run_unpacker, name, version) | 163 | if not url then |
| 164 | return nil, err | ||
| 165 | end | ||
| 163 | end | 166 | end |
| 167 | |||
| 168 | return run_unpacker(url, flags["force"]) | ||
| 164 | end | 169 | end |
| 165 | 170 | ||
| 166 | return unpack | 171 | return unpack |
diff --git a/src/luarocks/cmd/write_rockspec.lua b/src/luarocks/cmd/write_rockspec.lua index f3398a6a..36beffd0 100644 --- a/src/luarocks/cmd/write_rockspec.lua +++ b/src/luarocks/cmd/write_rockspec.lua | |||
| @@ -7,9 +7,9 @@ local fetch = require("luarocks.fetch") | |||
| 7 | local fs = require("luarocks.fs") | 7 | local fs = require("luarocks.fs") |
| 8 | local path = require("luarocks.path") | 8 | local path = require("luarocks.path") |
| 9 | local persist = require("luarocks.persist") | 9 | local persist = require("luarocks.persist") |
| 10 | local rockspecs = require("luarocks.rockspecs") | ||
| 10 | local type_rockspec = require("luarocks.type.rockspec") | 11 | local type_rockspec = require("luarocks.type.rockspec") |
| 11 | local util = require("luarocks.util") | 12 | local util = require("luarocks.util") |
| 12 | local vers = require("luarocks.core.vers") | ||
| 13 | 13 | ||
| 14 | write_rockspec.help_summary = "Write a template for a rockspec file." | 14 | write_rockspec.help_summary = "Write a template for a rockspec file." |
| 15 | write_rockspec.help_arguments = "[--output=<file> ...] [<name>] [<version>] [<url>|<path>]" | 15 | write_rockspec.help_arguments = "[--output=<file> ...] [<name>] [<version>] [<url>|<path>]" |
| @@ -46,7 +46,7 @@ local function open_file(name) | |||
| 46 | return io.open(dir.path(fs.current_dir(), name), "r") | 46 | return io.open(dir.path(fs.current_dir(), name), "r") |
| 47 | end | 47 | end |
| 48 | 48 | ||
| 49 | local function get_url(rockspec) | 49 | local function fetch_url(rockspec) |
| 50 | local file, temp_dir, err_code, err_file, err_temp_dir = fetch.fetch_sources(rockspec, false) | 50 | local file, temp_dir, err_code, err_file, err_temp_dir = fetch.fetch_sources(rockspec, false) |
| 51 | if err_code == "source.dir" then | 51 | if err_code == "source.dir" then |
| 52 | file, temp_dir = err_file, err_temp_dir | 52 | file, temp_dir = err_file, err_temp_dir |
| @@ -55,37 +55,78 @@ local function get_url(rockspec) | |||
| 55 | return false | 55 | return false |
| 56 | end | 56 | end |
| 57 | util.printout("File successfully downloaded. Making checksum and checking base dir...") | 57 | util.printout("File successfully downloaded. Making checksum and checking base dir...") |
| 58 | if fetch.is_basic_protocol(rockspec.source.protocol) then | 58 | if dir.is_basic_protocol(rockspec.source.protocol) then |
| 59 | rockspec.source.md5 = fs.get_md5(file) | 59 | rockspec.source.md5 = fs.get_md5(file) |
| 60 | end | 60 | end |
| 61 | local inferred_dir, found_dir = fetch.find_base_dir(file, temp_dir, rockspec.source.url) | 61 | local inferred_dir, found_dir = fetch.find_base_dir(file, temp_dir, rockspec.source.url) |
| 62 | return true, found_dir or inferred_dir, temp_dir | 62 | return true, found_dir or inferred_dir, temp_dir |
| 63 | end | 63 | end |
| 64 | 64 | ||
| 65 | local function configure_lua_version(rockspec, luaver) | 65 | local lua_version_dep = { |
| 66 | if luaver == "5.1" then | 66 | ["5.1"] = "lua ~> 5.1", |
| 67 | table.insert(rockspec.dependencies, "lua ~> 5.1") | 67 | ["5.2"] = "lua ~> 5.2", |
| 68 | elseif luaver == "5.2" then | 68 | ["5.3"] = "lua ~> 5.3", |
| 69 | table.insert(rockspec.dependencies, "lua ~> 5.2") | 69 | ["5.4"] = "lua ~> 5.4", |
| 70 | elseif luaver == "5.3" then | 70 | ["5.1,5.2"] = "lua >= 5.1, < 5.3", |
| 71 | table.insert(rockspec.dependencies, "lua ~> 5.3") | 71 | ["5.2,5.3"] = "lua >= 5.2, < 5.4", |
| 72 | elseif luaver == "5.4" then | 72 | ["5.3,5.4"] = "lua >= 5.3, < 5.5", |
| 73 | table.insert(rockspec.dependencies, "lua ~> 5.4") | 73 | ["5.1,5.2,5.3"] = "lua >= 5.1, < 5.4", |
| 74 | elseif luaver == "5.1,5.2" then | 74 | ["5.2,5.3,5.4"] = "lua >= 5.2, < 5.5", |
| 75 | table.insert(rockspec.dependencies, "lua >= 5.1, < 5.3") | 75 | ["5.1,5.2,5.3,5.4"] = "lua >= 5.1, < 5.5", |
| 76 | elseif luaver == "5.2,5.3" then | 76 | } |
| 77 | table.insert(rockspec.dependencies, "lua >= 5.2, < 5.4") | 77 | |
| 78 | elseif luaver == "5.3,5.4" then | 78 | local simple_scm_protocols = { |
| 79 | table.insert(rockspec.dependencies, "lua >= 5.3, < 5.5") | 79 | git = true, ["git+http"] = true, ["git+https"] = true, |
| 80 | elseif luaver == "5.1,5.2,5.3" then | 80 | hg = true, ["hg+http"] = true, ["hg+https"] = true |
| 81 | table.insert(rockspec.dependencies, "lua >= 5.1, < 5.4") | 81 | } |
| 82 | elseif luaver == "5.2,5.3,5.4" then | 82 | |
| 83 | table.insert(rockspec.dependencies, "lua >= 5.2, < 5.5") | 83 | local detect_url |
| 84 | elseif luaver == "5.1,5.2,5.3,5.4" then | 84 | do |
| 85 | table.insert(rockspec.dependencies, "lua >= 5.1, < 5.5") | 85 | local function detect_url_from_command(program, args, directory) |
| 86 | else | 86 | local command = fs.Q(cfg.variables[program:upper()]).. " "..args |
| 87 | util.warning("Please specify supported Lua version with --lua-version=<ver>. "..util.see_help("write_rockspec")) | 87 | local pipe = io.popen(fs.command_at(directory, fs.quiet_stderr(command))) |
| 88 | if not pipe then return nil end | ||
| 89 | local url = pipe:read("*a"):match("^([^\r\n]+)") | ||
| 90 | pipe:close() | ||
| 91 | if not url then return nil end | ||
| 92 | if not util.starts_with(url, program.."://") then | ||
| 93 | url = program.."+"..url | ||
| 94 | end | ||
| 95 | |||
| 96 | if simple_scm_protocols[dir.split_url(url)] then | ||
| 97 | return url | ||
| 98 | end | ||
| 99 | end | ||
| 100 | |||
| 101 | local function detect_scm_url(directory) | ||
| 102 | return detect_url_from_command("git", "config --get remote.origin.url", directory) or | ||
| 103 | detect_url_from_command("hg", "paths default", directory) | ||
| 88 | end | 104 | end |
| 105 | |||
| 106 | detect_url = function(url_or_dir) | ||
| 107 | if url_or_dir:match("://") then | ||
| 108 | return url_or_dir | ||
| 109 | else | ||
| 110 | return detect_scm_url(url_or_dir) or "*** please add URL for source tarball, zip or repository here ***" | ||
| 111 | end | ||
| 112 | end | ||
| 113 | end | ||
| 114 | |||
| 115 | local function detect_homepage(url, homepage) | ||
| 116 | if homepage then | ||
| 117 | return homepage | ||
| 118 | end | ||
| 119 | local url_protocol, url_path = dir.split_url(url) | ||
| 120 | |||
| 121 | if simple_scm_protocols[url_protocol] then | ||
| 122 | for _, domain in ipairs({"github.com", "bitbucket.org", "gitlab.com"}) do | ||
| 123 | if util.starts_with(url_path, domain) then | ||
| 124 | return "https://"..url_path:gsub("%.git$", "") | ||
| 125 | end | ||
| 126 | end | ||
| 127 | end | ||
| 128 | |||
| 129 | return "*** please enter a project homepage ***" | ||
| 89 | end | 130 | end |
| 90 | 131 | ||
| 91 | local function detect_description() | 132 | local function detect_description() |
| @@ -120,32 +161,6 @@ local function detect_mit_license(data) | |||
| 120 | return sum == 78656 | 161 | return sum == 78656 |
| 121 | end | 162 | end |
| 122 | 163 | ||
| 123 | local simple_scm_protocols = { | ||
| 124 | git = true, ["git+http"] = true, ["git+https"] = true, | ||
| 125 | hg = true, ["hg+http"] = true, ["hg+https"] = true | ||
| 126 | } | ||
| 127 | |||
| 128 | local function detect_url_from_command(program, args, directory) | ||
| 129 | local command = fs.Q(cfg.variables[program:upper()]).. " "..args | ||
| 130 | local pipe = io.popen(fs.command_at(directory, fs.quiet_stderr(command))) | ||
| 131 | if not pipe then return nil end | ||
| 132 | local url = pipe:read("*a"):match("^([^\r\n]+)") | ||
| 133 | pipe:close() | ||
| 134 | if not url then return nil end | ||
| 135 | if not util.starts_with(url, program.."://") then | ||
| 136 | url = program.."+"..url | ||
| 137 | end | ||
| 138 | |||
| 139 | if simple_scm_protocols[dir.split_url(url)] then | ||
| 140 | return url | ||
| 141 | end | ||
| 142 | end | ||
| 143 | |||
| 144 | local function detect_scm_url(directory) | ||
| 145 | return detect_url_from_command("git", "config --get remote.origin.url", directory) or | ||
| 146 | detect_url_from_command("hg", "paths default", directory) | ||
| 147 | end | ||
| 148 | |||
| 149 | local function check_license() | 164 | local function check_license() |
| 150 | local fd = open_file("COPYING") or open_file("LICENSE") or open_file("MIT-LICENSE.txt") | 165 | local fd = open_file("COPYING") or open_file("LICENSE") or open_file("MIT-LICENSE.txt") |
| 151 | if not fd then return nil end | 166 | if not fd then return nil end |
| @@ -182,7 +197,7 @@ local function fill_as_builtin(rockspec, libs) | |||
| 182 | break | 197 | break |
| 183 | end | 198 | end |
| 184 | end | 199 | end |
| 185 | 200 | ||
| 186 | local incdirs, libdirs | 201 | local incdirs, libdirs |
| 187 | if libs then | 202 | if libs then |
| 188 | incdirs, libdirs = {}, {} | 203 | incdirs, libdirs = {}, {} |
| @@ -259,7 +274,7 @@ function write_rockspec.command(flags, name, version, url_or_dir) | |||
| 259 | if pathname == "." then | 274 | if pathname == "." then |
| 260 | name = name or dir.base_name(fs.current_dir()) | 275 | name = name or dir.base_name(fs.current_dir()) |
| 261 | end | 276 | end |
| 262 | elseif fetch.is_basic_protocol(protocol) then | 277 | elseif dir.is_basic_protocol(protocol) then |
| 263 | local filename = dir.base_name(url_or_dir) | 278 | local filename = dir.base_name(url_or_dir) |
| 264 | local newname, newversion = filename:match("(.*)-([^-]+)") | 279 | local newname, newversion = filename:match("(.*)-([^-]+)") |
| 265 | if newname then | 280 | if newname then |
| @@ -276,48 +291,47 @@ function write_rockspec.command(flags, name, version, url_or_dir) | |||
| 276 | version = version or "dev" | 291 | version = version or "dev" |
| 277 | 292 | ||
| 278 | local filename = flags["output"] or dir.path(fs.current_dir(), name:lower().."-"..version.."-1.rockspec") | 293 | local filename = flags["output"] or dir.path(fs.current_dir(), name:lower().."-"..version.."-1.rockspec") |
| 279 | 294 | ||
| 280 | local rockspec = { | 295 | local url = detect_url(url_or_dir) |
| 296 | local homepage = detect_homepage(url, flags["homepage"]) | ||
| 297 | |||
| 298 | local rockspec, err = rockspecs.from_persisted_table(filename, { | ||
| 281 | rockspec_format = flags["rockspec-format"], | 299 | rockspec_format = flags["rockspec-format"], |
| 282 | package = name, | 300 | package = name, |
| 283 | name = name:lower(), | ||
| 284 | version = version.."-1", | 301 | version = version.."-1", |
| 285 | source = { | 302 | source = { |
| 286 | url = "*** please add URL for source tarball, zip or repository here ***", | 303 | url = url, |
| 287 | tag = flags["tag"], | 304 | tag = flags["tag"], |
| 288 | }, | 305 | }, |
| 289 | description = { | 306 | description = { |
| 290 | summary = flags["summary"] or "*** please specify description summary ***", | 307 | summary = flags["summary"] or "*** please specify description summary ***", |
| 291 | detailed = flags["detailed"] or "*** please enter a detailed description ***", | 308 | detailed = flags["detailed"] or "*** please enter a detailed description ***", |
| 292 | homepage = flags["homepage"] or "*** please enter a project homepage ***", | 309 | homepage = homepage, |
| 293 | license = flags["license"] or "*** please specify a license ***", | 310 | license = flags["license"] or "*** please specify a license ***", |
| 294 | }, | 311 | }, |
| 295 | dependencies = {}, | 312 | dependencies = { |
| 313 | lua_version_dep[flags["lua-version"]], | ||
| 314 | }, | ||
| 296 | build = {}, | 315 | build = {}, |
| 297 | } | 316 | }) |
| 298 | path.configure_paths(rockspec) | 317 | assert(not err, err) |
| 299 | rockspec.source.protocol = protocol | 318 | rockspec.source.protocol = protocol |
| 300 | 319 | ||
| 301 | local parsed_format = vers.parse_version(rockspec.rockspec_format or "1.0") | 320 | if not next(rockspec.dependencies) then |
| 302 | rockspec.format_is_at_least = function(_, v) | 321 | util.warning("Please specify supported Lua version with --lua-version=<ver>. "..util.see_help("write_rockspec")) |
| 303 | return parsed_format >= vers.parse_version(v) | ||
| 304 | end | 322 | end |
| 305 | 323 | ||
| 306 | configure_lua_version(rockspec, flags["lua-version"]) | ||
| 307 | |||
| 308 | local local_dir = url_or_dir | 324 | local local_dir = url_or_dir |
| 309 | 325 | ||
| 310 | if url_or_dir:match("://") then | 326 | if url_or_dir:match("://") then |
| 311 | rockspec.source.url = url_or_dir | ||
| 312 | rockspec.source.file = dir.base_name(url_or_dir) | 327 | rockspec.source.file = dir.base_name(url_or_dir) |
| 313 | rockspec.source.dir = "dummy" | 328 | if not dir.is_basic_protocol(rockspec.source.protocol) then |
| 314 | if not fetch.is_basic_protocol(rockspec.source.protocol) then | ||
| 315 | if version ~= "dev" then | 329 | if version ~= "dev" then |
| 316 | rockspec.source.tag = flags["tag"] or "v" .. version | 330 | rockspec.source.tag = flags["tag"] or "v" .. version |
| 317 | end | 331 | end |
| 318 | end | 332 | end |
| 319 | rockspec.source.dir = nil | 333 | rockspec.source.dir = nil |
| 320 | local ok, base_dir, temp_dir = get_url(rockspec) | 334 | local ok, base_dir, temp_dir = fetch_url(rockspec) |
| 321 | if ok then | 335 | if ok then |
| 322 | if base_dir ~= dir.base_name(url_or_dir) then | 336 | if base_dir ~= dir.base_name(url_or_dir) then |
| 323 | rockspec.source.dir = base_dir | 337 | rockspec.source.dir = base_dir |
| @@ -328,26 +342,11 @@ function write_rockspec.command(flags, name, version, url_or_dir) | |||
| 328 | else | 342 | else |
| 329 | local_dir = nil | 343 | local_dir = nil |
| 330 | end | 344 | end |
| 331 | else | ||
| 332 | rockspec.source.url = detect_scm_url(local_dir) or rockspec.source.url | ||
| 333 | end | 345 | end |
| 334 | 346 | ||
| 335 | if not local_dir then | 347 | if not local_dir then |
| 336 | local_dir = "." | 348 | local_dir = "." |
| 337 | end | 349 | end |
| 338 | |||
| 339 | if not flags["homepage"] then | ||
| 340 | local url_protocol, url_path = dir.split_url(rockspec.source.url) | ||
| 341 | |||
| 342 | if simple_scm_protocols[url_protocol] then | ||
| 343 | for _, domain in ipairs({"github.com", "bitbucket.org", "gitlab.com"}) do | ||
| 344 | if util.starts_with(url_path, domain) then | ||
| 345 | rockspec.description.homepage = "https://"..url_path:gsub("%.git$", "") | ||
| 346 | break | ||
| 347 | end | ||
| 348 | end | ||
| 349 | end | ||
| 350 | end | ||
| 351 | 350 | ||
| 352 | local libs = nil | 351 | local libs = nil |
| 353 | if flags["lib"] then | 352 | if flags["lib"] then |
| @@ -364,7 +363,7 @@ function write_rockspec.command(flags, name, version, url_or_dir) | |||
| 364 | local ok, err = fs.change_dir(local_dir) | 363 | local ok, err = fs.change_dir(local_dir) |
| 365 | if not ok then return nil, "Failed reaching files from project - error entering directory "..local_dir end | 364 | if not ok then return nil, "Failed reaching files from project - error entering directory "..local_dir end |
| 366 | 365 | ||
| 367 | if (not flags["summary"]) or (not flags["detailed"]) then | 366 | if not (flags["summary"] and flags["detailed"]) then |
| 368 | local summary, detailed = detect_description() | 367 | local summary, detailed = detect_description() |
| 369 | rockspec.description.summary = flags["summary"] or summary | 368 | rockspec.description.summary = flags["summary"] or summary |
| 370 | rockspec.description.detailed = flags["detailed"] or detailed | 369 | rockspec.description.detailed = flags["detailed"] or detailed |
diff --git a/src/luarocks/command_line.lua b/src/luarocks/command_line.lua index a9cf9968..7d9cc4af 100644 --- a/src/luarocks/command_line.lua +++ b/src/luarocks/command_line.lua | |||
| @@ -23,7 +23,7 @@ end | |||
| 23 | -- @param message string: The error message. | 23 | -- @param message string: The error message. |
| 24 | -- @param exitcode number: the exitcode to use | 24 | -- @param exitcode number: the exitcode to use |
| 25 | local function die(message, exitcode) | 25 | local function die(message, exitcode) |
| 26 | assert(type(message) == "string") | 26 | assert(type(message) == "string", "bad error, expected string, got: " .. type(message)) |
| 27 | util.printerr("\nError: "..message) | 27 | util.printerr("\nError: "..message) |
| 28 | 28 | ||
| 29 | local ok, err = xpcall(util.run_scheduled_functions, error_handler) | 29 | local ok, err = xpcall(util.run_scheduled_functions, error_handler) |
| @@ -138,10 +138,6 @@ function command_line.run_command(...) | |||
| 138 | die("Invalid entry for --deps-mode.") | 138 | die("Invalid entry for --deps-mode.") |
| 139 | end | 139 | end |
| 140 | 140 | ||
| 141 | if flags["branch"] then | ||
| 142 | cfg.branch = flags["branch"] | ||
| 143 | end | ||
| 144 | |||
| 145 | if flags["tree"] then | 141 | if flags["tree"] then |
| 146 | local named = false | 142 | local named = false |
| 147 | for _, tree in ipairs(cfg.rocks_trees) do | 143 | for _, tree in ipairs(cfg.rocks_trees) do |
diff --git a/src/luarocks/core/util.lua b/src/luarocks/core/util.lua index 68fd931d..3582cb54 100644 --- a/src/luarocks/core/util.lua +++ b/src/luarocks/core/util.lua | |||
| @@ -116,7 +116,6 @@ end | |||
| 116 | --- Merges contents of src on top of dst's contents. | 116 | --- Merges contents of src on top of dst's contents. |
| 117 | -- @param dst Destination table, which will receive src's contents. | 117 | -- @param dst Destination table, which will receive src's contents. |
| 118 | -- @param src Table which provides new contents to dst. | 118 | -- @param src Table which provides new contents to dst. |
| 119 | -- @see platform_overrides | ||
| 120 | function util.deep_merge(dst, src) | 119 | function util.deep_merge(dst, src) |
| 121 | for k, v in pairs(src) do | 120 | for k, v in pairs(src) do |
| 122 | if type(v) == "table" then | 121 | if type(v) == "table" then |
diff --git a/src/luarocks/deps.lua b/src/luarocks/deps.lua index b1ff6c47..3ec1aa93 100644 --- a/src/luarocks/deps.lua +++ b/src/luarocks/deps.lua | |||
| @@ -14,7 +14,7 @@ local queries = require("luarocks.queries") | |||
| 14 | -- @param dep table: A dependency parsed in table format. | 14 | -- @param dep table: A dependency parsed in table format. |
| 15 | -- @param blacklist table: Versions that can't be accepted. Table where keys | 15 | -- @param blacklist table: Versions that can't be accepted. Table where keys |
| 16 | -- are program versions and values are 'true'. | 16 | -- are program versions and values are 'true'. |
| 17 | -- @param rocks_provided table: A table of auto-dependencies provided | 17 | -- @param rocks_provided table: A table of auto-provided dependencies. |
| 18 | -- by this Lua implementation for the given dependency. | 18 | -- by this Lua implementation for the given dependency. |
| 19 | -- @return string or nil: latest installed version of the rock matching the dependency | 19 | -- @return string or nil: latest installed version of the rock matching the dependency |
| 20 | -- or nil if it could not be matched. | 20 | -- or nil if it could not be matched. |
| @@ -48,7 +48,8 @@ local function match_dep(dep, blacklist, deps_mode, rocks_provided) | |||
| 48 | end | 48 | end |
| 49 | 49 | ||
| 50 | --- Attempt to match dependencies of a rockspec to installed rocks. | 50 | --- Attempt to match dependencies of a rockspec to installed rocks. |
| 51 | -- @param rockspec table: The rockspec loaded as a table. | 51 | -- @param dependencies table: The table of dependencies. |
| 52 | -- @param rocks_provided table: The table of auto-provided dependencies. | ||
| 52 | -- @param blacklist table or nil: Program versions to not use as valid matches. | 53 | -- @param blacklist table or nil: Program versions to not use as valid matches. |
| 53 | -- Table where keys are program names and values are tables where keys | 54 | -- Table where keys are program names and values are tables where keys |
| 54 | -- are program versions and values are 'true'. | 55 | -- are program versions and values are 'true'. |
| @@ -58,15 +59,14 @@ end | |||
| 58 | -- parsed as tables; and a table of "no-upgrade" missing dependencies | 59 | -- parsed as tables; and a table of "no-upgrade" missing dependencies |
| 59 | -- (to be used in plugin modules so that a plugin does not force upgrade of | 60 | -- (to be used in plugin modules so that a plugin does not force upgrade of |
| 60 | -- its parent application). | 61 | -- its parent application). |
| 61 | function deps.match_deps(rockspec, blacklist, deps_mode) | 62 | function deps.match_deps(dependencies, rocks_provided, blacklist, deps_mode) |
| 62 | assert(type(rockspec) == "table") | ||
| 63 | assert(type(blacklist) == "table" or not blacklist) | 63 | assert(type(blacklist) == "table" or not blacklist) |
| 64 | local matched, missing, no_upgrade = {}, {}, {} | 64 | local matched, missing, no_upgrade = {}, {}, {} |
| 65 | 65 | ||
| 66 | for _, dep in ipairs(rockspec.dependencies) do | 66 | for _, dep in ipairs(dependencies) do |
| 67 | local found = match_dep(dep, blacklist and blacklist[dep.name] or nil, deps_mode, rockspec.rocks_provided) | 67 | local found = match_dep(dep, blacklist and blacklist[dep.name] or nil, deps_mode, rocks_provided) |
| 68 | if found then | 68 | if found then |
| 69 | if not rockspec.rocks_provided[dep.name] then | 69 | if not rocks_provided[dep.name] then |
| 70 | matched[dep] = {name = dep.name, version = found} | 70 | matched[dep] = {name = dep.name, version = found} |
| 71 | end | 71 | end |
| 72 | else | 72 | else |
| @@ -266,7 +266,7 @@ end | |||
| 266 | -- @return boolean or (nil, string): True if no errors occurred, or | 266 | -- @return boolean or (nil, string): True if no errors occurred, or |
| 267 | -- nil and an error message if any test failed. | 267 | -- nil and an error message if any test failed. |
| 268 | function deps.check_external_deps(rockspec, mode) | 268 | function deps.check_external_deps(rockspec, mode) |
| 269 | assert(type(rockspec) == "table") | 269 | assert(rockspec:type() == "rockspec") |
| 270 | 270 | ||
| 271 | local fs = require("luarocks.fs") | 271 | local fs = require("luarocks.fs") |
| 272 | 272 | ||
| @@ -431,25 +431,24 @@ function deps.scan_deps(results, manifest, name, version, deps_mode) | |||
| 431 | return | 431 | return |
| 432 | end | 432 | end |
| 433 | if not manifest.dependencies then manifest.dependencies = {} end | 433 | if not manifest.dependencies then manifest.dependencies = {} end |
| 434 | local dependencies = manifest.dependencies | 434 | local md = manifest.dependencies |
| 435 | if not dependencies[name] then dependencies[name] = {} end | 435 | if not md[name] then md[name] = {} end |
| 436 | local dependencies_name = dependencies[name] | 436 | local mdn = md[name] |
| 437 | local deplist = dependencies_name[version] | 437 | local dependencies = mdn[version] |
| 438 | local rockspec, err | 438 | local rocks_provided |
| 439 | if not deplist then | 439 | if not dependencies then |
| 440 | rockspec, err = fetch.load_local_rockspec(path.rockspec_file(name, version), false) | 440 | local rockspec, err = fetch.load_local_rockspec(path.rockspec_file(name, version), false) |
| 441 | if not rockspec then | 441 | if not rockspec then |
| 442 | util.printerr("Couldn't load rockspec for "..name.." "..version..": "..err) | 442 | util.printerr("Couldn't load rockspec for "..name.." "..version..": "..err) |
| 443 | return | 443 | return |
| 444 | end | 444 | end |
| 445 | dependencies_name[version] = rockspec.dependencies | 445 | dependencies = rockspec.dependencies |
| 446 | rocks_provided = rockspec.rocks_provided | ||
| 447 | mdn[version] = dependencies | ||
| 446 | else | 448 | else |
| 447 | rockspec = { | 449 | rocks_provided = setmetatable({}, { __index = cfg.rocks_provided_3_0 }) |
| 448 | dependencies = deplist, | ||
| 449 | rocks_provided = setmetatable({}, { __index = cfg.rocks_provided_3_0 }) | ||
| 450 | } | ||
| 451 | end | 450 | end |
| 452 | local matched = deps.match_deps(rockspec, nil, deps_mode) | 451 | local matched = deps.match_deps(dependencies, rocks_provided, nil, deps_mode) |
| 453 | results[name] = version | 452 | results[name] = version |
| 454 | for _, match in pairs(matched) do | 453 | for _, match in pairs(matched) do |
| 455 | deps.scan_deps(results, manifest, match.name, match.version, deps_mode) | 454 | deps.scan_deps(results, manifest, match.name, match.version, deps_mode) |
diff --git a/src/luarocks/dir.lua b/src/luarocks/dir.lua index 72395e47..679e8f0d 100644 --- a/src/luarocks/dir.lua +++ b/src/luarocks/dir.lua | |||
| @@ -40,4 +40,20 @@ function dir.normalize(name) | |||
| 40 | return pathname | 40 | return pathname |
| 41 | end | 41 | end |
| 42 | 42 | ||
| 43 | --- Returns true if protocol does not require additional tools. | ||
| 44 | -- @param protocol The protocol name | ||
| 45 | function dir.is_basic_protocol(protocol) | ||
| 46 | return protocol == "http" or protocol == "https" or protocol == "ftp" or protocol == "file" | ||
| 47 | end | ||
| 48 | |||
| 49 | function dir.deduce_base_dir(url) | ||
| 50 | -- for extensions like foo.tar.gz, "gz" is stripped first | ||
| 51 | local known_exts = {} | ||
| 52 | for _, ext in ipairs{"zip", "git", "tgz", "tar", "gz", "bz2"} do | ||
| 53 | known_exts[ext] = "" | ||
| 54 | end | ||
| 55 | local base = dir.base_name(url) | ||
| 56 | return (base:gsub("%.([^.]*)$", known_exts):gsub("%.tar", "")) | ||
| 57 | end | ||
| 58 | |||
| 43 | return dir | 59 | return dir |
diff --git a/src/luarocks/fetch.lua b/src/luarocks/fetch.lua index 9ea2b487..074b0e45 100644 --- a/src/luarocks/fetch.lua +++ b/src/luarocks/fetch.lua | |||
| @@ -4,18 +4,11 @@ local fetch = {} | |||
| 4 | 4 | ||
| 5 | local fs = require("luarocks.fs") | 5 | local fs = require("luarocks.fs") |
| 6 | local dir = require("luarocks.dir") | 6 | local dir = require("luarocks.dir") |
| 7 | local type_rockspec = require("luarocks.type.rockspec") | 7 | local rockspecs = require("luarocks.rockspecs") |
| 8 | local path = require("luarocks.path") | ||
| 9 | local vers = require("luarocks.core.vers") | ||
| 10 | local queries = require("luarocks.queries") | ||
| 11 | local persist = require("luarocks.persist") | 8 | local persist = require("luarocks.persist") |
| 12 | local util = require("luarocks.util") | 9 | local util = require("luarocks.util") |
| 13 | local cfg = require("luarocks.core.cfg") | 10 | local cfg = require("luarocks.core.cfg") |
| 14 | 11 | ||
| 15 | function fetch.is_basic_protocol(protocol, remote) | ||
| 16 | return protocol == "http" or protocol == "https" or protocol == "ftp" or (not remote and protocol == "file") | ||
| 17 | end | ||
| 18 | |||
| 19 | --- Fetch a local or remote file. | 12 | --- Fetch a local or remote file. |
| 20 | -- Make a remote or local URL/pathname local, fetching the file if necessary. | 13 | -- Make a remote or local URL/pathname local, fetching the file if necessary. |
| 21 | -- Other "fetch" and "load" functions use this function to obtain files. | 14 | -- Other "fetch" and "load" functions use this function to obtain files. |
| @@ -37,7 +30,7 @@ function fetch.fetch_url(url, filename, cache) | |||
| 37 | local protocol, pathname = dir.split_url(url) | 30 | local protocol, pathname = dir.split_url(url) |
| 38 | if protocol == "file" then | 31 | if protocol == "file" then |
| 39 | return fs.absolute_name(pathname) | 32 | return fs.absolute_name(pathname) |
| 40 | elseif fetch.is_basic_protocol(protocol, true) then | 33 | elseif dir.is_basic_protocol(protocol) then |
| 41 | local ok, name = fs.download(url, filename, cache) | 34 | local ok, name = fs.download(url, filename, cache) |
| 42 | if not ok then | 35 | if not ok then |
| 43 | return nil, "Failed downloading "..url..(filename and " - "..filename or ""), "network" | 36 | return nil, "Failed downloading "..url..(filename and " - "..filename or ""), "network" |
| @@ -105,7 +98,7 @@ function fetch.find_base_dir(file, temp_dir, src_url, src_dir) | |||
| 105 | local ok, err = fs.change_dir(temp_dir) | 98 | local ok, err = fs.change_dir(temp_dir) |
| 106 | if not ok then return nil, err end | 99 | if not ok then return nil, err end |
| 107 | fs.unpack_archive(file) | 100 | fs.unpack_archive(file) |
| 108 | local inferred_dir = src_dir or fetch.url_to_base_dir(src_url) | 101 | local inferred_dir = src_dir or dir.deduce_base_dir(src_url) |
| 109 | local found_dir = nil | 102 | local found_dir = nil |
| 110 | if fs.exists(inferred_dir) then | 103 | if fs.exists(inferred_dir) then |
| 111 | found_dir = inferred_dir | 104 | found_dir = inferred_dir |
| @@ -170,131 +163,39 @@ function fetch.fetch_and_unpack_rock(rock_file, dest) | |||
| 170 | return unpack_dir | 163 | return unpack_dir |
| 171 | end | 164 | end |
| 172 | 165 | ||
| 173 | function fetch.url_to_base_dir(url) | ||
| 174 | -- for extensions like foo.tar.gz, "gz" is stripped first | ||
| 175 | local known_exts = {} | ||
| 176 | for _, ext in ipairs{"zip", "git", "tgz", "tar", "gz", "bz2"} do | ||
| 177 | known_exts[ext] = "" | ||
| 178 | end | ||
| 179 | local base = dir.base_name(url) | ||
| 180 | return (base:gsub("%.([^.]*)$", known_exts):gsub("%.tar", "")) | ||
| 181 | end | ||
| 182 | |||
| 183 | local function convert_dependencies(rockspec, key) | ||
| 184 | if rockspec[key] then | ||
| 185 | for i = 1, #rockspec[key] do | ||
| 186 | local parsed, err = queries.from_dep_string(rockspec[key][i]) | ||
| 187 | if not parsed then | ||
| 188 | return nil, "Parse error processing dependency '"..rockspec[key][i].."': "..tostring(err) | ||
| 189 | end | ||
| 190 | rockspec[key][i] = parsed | ||
| 191 | end | ||
| 192 | else | ||
| 193 | rockspec[key] = {} | ||
| 194 | end | ||
| 195 | end | ||
| 196 | |||
| 197 | --- Back-end function that actually loads the local rockspec. | 166 | --- Back-end function that actually loads the local rockspec. |
| 198 | -- Performs some validation and postprocessing of the rockspec contents. | 167 | -- Performs some validation and postprocessing of the rockspec contents. |
| 199 | -- @param filename string: The local filename of the rockspec file. | 168 | -- @param rel_filename string: The local filename of the rockspec file. |
| 200 | -- @param quick boolean: if true, skips some steps when loading | 169 | -- @param quick boolean: if true, skips some steps when loading |
| 201 | -- rockspec. | 170 | -- rockspec. |
| 202 | -- @return table or (nil, string): A table representing the rockspec | 171 | -- @return table or (nil, string): A table representing the rockspec |
| 203 | -- or nil followed by an error message. | 172 | -- or nil followed by an error message. |
| 204 | function fetch.load_local_rockspec(filename, quick) | 173 | function fetch.load_local_rockspec(rel_filename, quick) |
| 205 | assert(type(filename) == "string") | 174 | assert(type(rel_filename) == "string") |
| 206 | filename = fs.absolute_name(filename) | 175 | local abs_filename = fs.absolute_name(rel_filename) |
| 207 | local rockspec, err = persist.load_into_table(filename) | ||
| 208 | if not rockspec then | ||
| 209 | return nil, "Could not load rockspec file "..filename.." ("..err..")" | ||
| 210 | end | ||
| 211 | if cfg.branch and (type(rockspec.source) == "table") then | ||
| 212 | rockspec.source.branch = cfg.branch | ||
| 213 | end | ||
| 214 | local globals = err | ||
| 215 | |||
| 216 | if rockspec.rockspec_format then | ||
| 217 | if vers.compare_versions(rockspec.rockspec_format, type_rockspec.rockspec_format) then | ||
| 218 | return nil, "Rockspec format "..rockspec.rockspec_format.." is not supported, please upgrade LuaRocks." | ||
| 219 | end | ||
| 220 | end | ||
| 221 | |||
| 222 | if not quick then | ||
| 223 | local ok, err = type_rockspec.check(rockspec, globals) | ||
| 224 | if not ok then | ||
| 225 | return nil, filename..": "..err | ||
| 226 | end | ||
| 227 | end | ||
| 228 | |||
| 229 | --- Check if rockspec format version satisfies version requirement. | ||
| 230 | -- @param rockspec table: The rockspec table. | ||
| 231 | -- @param version string: required version. | ||
| 232 | -- @return boolean: true if rockspec format matches version or is newer, false otherwise. | ||
| 233 | do | ||
| 234 | local parsed_format = vers.parse_version(rockspec.rockspec_format or "1.0") | ||
| 235 | rockspec.format_is_at_least = function(self, version) | ||
| 236 | return parsed_format >= vers.parse_version(version) | ||
| 237 | end | ||
| 238 | end | ||
| 239 | 176 | ||
| 240 | util.platform_overrides(rockspec.build) | 177 | local basename = dir.base_name(abs_filename) |
| 241 | util.platform_overrides(rockspec.dependencies) | 178 | if basename ~= "rockspec" then |
| 242 | util.platform_overrides(rockspec.build_dependencies) | 179 | if not basename:match("(.*)%-[^-]*%-[0-9]*") then |
| 243 | util.platform_overrides(rockspec.test_dependencies) | ||
| 244 | util.platform_overrides(rockspec.external_dependencies) | ||
| 245 | util.platform_overrides(rockspec.source) | ||
| 246 | util.platform_overrides(rockspec.hooks) | ||
| 247 | util.platform_overrides(rockspec.test) | ||
| 248 | |||
| 249 | local basename = dir.base_name(filename) | ||
| 250 | if basename == "rockspec" then | ||
| 251 | rockspec.name = rockspec.package:lower() | ||
| 252 | else | ||
| 253 | rockspec.name = basename:match("(.*)-[^-]*-[0-9]*") | ||
| 254 | if not rockspec.name then | ||
| 255 | return nil, "Expected filename in format 'name-version-revision.rockspec'." | 180 | return nil, "Expected filename in format 'name-version-revision.rockspec'." |
| 256 | end | 181 | end |
| 257 | end | 182 | end |
| 258 | 183 | ||
| 259 | local protocol, pathname = dir.split_url(rockspec.source.url) | 184 | local tbl, err = persist.load_into_table(abs_filename) |
| 260 | if fetch.is_basic_protocol(protocol) then | 185 | if not tbl then |
| 261 | rockspec.source.file = rockspec.source.file or dir.base_name(rockspec.source.url) | 186 | return nil, "Could not load rockspec file "..abs_filename.." ("..err..")" |
| 187 | end | ||
| 188 | |||
| 189 | local rockspec, err = rockspecs.from_persisted_table(abs_filename, tbl, err, quick) | ||
| 190 | if not rockspec then | ||
| 191 | return nil, abs_filename .. ": " .. err | ||
| 262 | end | 192 | end |
| 263 | rockspec.source.protocol, rockspec.source.pathname = protocol, pathname | ||
| 264 | |||
| 265 | -- Temporary compatibility | ||
| 266 | if rockspec.source.cvs_module then rockspec.source.module = rockspec.source.cvs_module end | ||
| 267 | if rockspec.source.cvs_tag then rockspec.source.tag = rockspec.source.cvs_tag end | ||
| 268 | 193 | ||
| 269 | local name_version = rockspec.package:lower() .. "-" .. rockspec.version | 194 | local name_version = rockspec.package:lower() .. "-" .. rockspec.version |
| 270 | if basename ~= "rockspec" and basename ~= name_version .. ".rockspec" then | 195 | if basename ~= "rockspec" and basename ~= name_version .. ".rockspec" then |
| 271 | return nil, "Inconsistency between rockspec filename ("..basename..") and its contents ("..name_version..".rockspec)." | 196 | return nil, "Inconsistency between rockspec filename ("..basename..") and its contents ("..name_version..".rockspec)." |
| 272 | end | 197 | end |
| 273 | 198 | ||
| 274 | rockspec.local_filename = filename | ||
| 275 | local filebase = rockspec.source.file or rockspec.source.url | ||
| 276 | local base = fetch.url_to_base_dir(filebase) | ||
| 277 | rockspec.source.dir_set = rockspec.source.dir ~= nil | ||
| 278 | rockspec.source.dir = rockspec.source.dir | ||
| 279 | or rockspec.source.module | ||
| 280 | or ( (filebase:match("%.lua$") or filebase:match("%.c$")) | ||
| 281 | and (rockspec:format_is_at_least("3.0") | ||
| 282 | and (fetch.is_basic_protocol(protocol) and "." or base) | ||
| 283 | or ".") ) | ||
| 284 | or base | ||
| 285 | |||
| 286 | rockspec.rocks_provided = (rockspec:format_is_at_least("3.0") | ||
| 287 | and cfg.rocks_provided_3_0 | ||
| 288 | or cfg.rocks_provided) | ||
| 289 | |||
| 290 | convert_dependencies(rockspec, "dependencies") | ||
| 291 | convert_dependencies(rockspec, "build_dependencies") | ||
| 292 | convert_dependencies(rockspec, "test_dependencies") | ||
| 293 | |||
| 294 | if not quick then | ||
| 295 | path.configure_paths(rockspec) | ||
| 296 | end | ||
| 297 | |||
| 298 | return rockspec | 199 | return rockspec |
| 299 | end | 200 | end |
| 300 | 201 | ||
| @@ -347,7 +248,7 @@ end | |||
| 347 | -- the fetched source tarball and the temporary directory created to | 248 | -- the fetched source tarball and the temporary directory created to |
| 348 | -- store it; or nil and an error message and optional error code. | 249 | -- store it; or nil and an error message and optional error code. |
| 349 | function fetch.get_sources(rockspec, extract, dest_dir) | 250 | function fetch.get_sources(rockspec, extract, dest_dir) |
| 350 | assert(type(rockspec) == "table") | 251 | assert(rockspec:type() == "rockspec") |
| 351 | assert(type(extract) == "boolean") | 252 | assert(type(extract) == "boolean") |
| 352 | assert(type(dest_dir) == "string" or not dest_dir) | 253 | assert(type(dest_dir) == "string" or not dest_dir) |
| 353 | 254 | ||
| @@ -417,13 +318,13 @@ end | |||
| 417 | -- the fetched source tarball and the temporary directory created to | 318 | -- the fetched source tarball and the temporary directory created to |
| 418 | -- store it; or nil and an error message. | 319 | -- store it; or nil and an error message. |
| 419 | function fetch.fetch_sources(rockspec, extract, dest_dir) | 320 | function fetch.fetch_sources(rockspec, extract, dest_dir) |
| 420 | assert(type(rockspec) == "table") | 321 | assert(rockspec:type() == "rockspec") |
| 421 | assert(type(extract) == "boolean") | 322 | assert(type(extract) == "boolean") |
| 422 | assert(type(dest_dir) == "string" or not dest_dir) | 323 | assert(type(dest_dir) == "string" or not dest_dir) |
| 423 | 324 | ||
| 424 | local protocol = rockspec.source.protocol | 325 | local protocol = rockspec.source.protocol |
| 425 | local ok, proto | 326 | local ok, proto |
| 426 | if fetch.is_basic_protocol(protocol) then | 327 | if dir.is_basic_protocol(protocol) then |
| 427 | proto = fetch | 328 | proto = fetch |
| 428 | else | 329 | else |
| 429 | ok, proto = pcall(require, "luarocks.fetch."..protocol:gsub("[+-]", "_")) | 330 | ok, proto = pcall(require, "luarocks.fetch."..protocol:gsub("[+-]", "_")) |
diff --git a/src/luarocks/fetch/cvs.lua b/src/luarocks/fetch/cvs.lua index ece711b6..d78e6e60 100644 --- a/src/luarocks/fetch/cvs.lua +++ b/src/luarocks/fetch/cvs.lua | |||
| @@ -16,7 +16,7 @@ local util = require("luarocks.util") | |||
| 16 | -- the fetched source tarball and the temporary directory created to | 16 | -- the fetched source tarball and the temporary directory created to |
| 17 | -- store it; or nil and an error message. | 17 | -- store it; or nil and an error message. |
| 18 | function cvs.get_sources(rockspec, extract, dest_dir) | 18 | function cvs.get_sources(rockspec, extract, dest_dir) |
| 19 | assert(type(rockspec) == "table") | 19 | assert(rockspec:type() == "rockspec") |
| 20 | assert(type(dest_dir) == "string" or not dest_dir) | 20 | assert(type(dest_dir) == "string" or not dest_dir) |
| 21 | 21 | ||
| 22 | local cvs_cmd = rockspec.variables.CVS | 22 | local cvs_cmd = rockspec.variables.CVS |
diff --git a/src/luarocks/fetch/git.lua b/src/luarocks/fetch/git.lua index a14a5bfb..49ee7183 100644 --- a/src/luarocks/fetch/git.lua +++ b/src/luarocks/fetch/git.lua | |||
| @@ -77,7 +77,7 @@ end | |||
| 77 | -- the fetched source tarball and the temporary directory created to | 77 | -- the fetched source tarball and the temporary directory created to |
| 78 | -- store it; or nil and an error message. | 78 | -- store it; or nil and an error message. |
| 79 | function git.get_sources(rockspec, extract, dest_dir, depth) | 79 | function git.get_sources(rockspec, extract, dest_dir, depth) |
| 80 | assert(type(rockspec) == "table") | 80 | assert(rockspec:type() == "rockspec") |
| 81 | assert(type(dest_dir) == "string" or not dest_dir) | 81 | assert(type(dest_dir) == "string" or not dest_dir) |
| 82 | 82 | ||
| 83 | local git_cmd = rockspec.variables.GIT | 83 | local git_cmd = rockspec.variables.GIT |
diff --git a/src/luarocks/fetch/hg.lua b/src/luarocks/fetch/hg.lua index 4cf8d028..0ef0f5e4 100644 --- a/src/luarocks/fetch/hg.lua +++ b/src/luarocks/fetch/hg.lua | |||
| @@ -16,7 +16,7 @@ local util = require("luarocks.util") | |||
| 16 | -- the fetched source tarball and the temporary directory created to | 16 | -- the fetched source tarball and the temporary directory created to |
| 17 | -- store it; or nil and an error message. | 17 | -- store it; or nil and an error message. |
| 18 | function hg.get_sources(rockspec, extract, dest_dir) | 18 | function hg.get_sources(rockspec, extract, dest_dir) |
| 19 | assert(type(rockspec) == "table") | 19 | assert(rockspec:type() == "rockspec") |
| 20 | assert(type(dest_dir) == "string" or not dest_dir) | 20 | assert(type(dest_dir) == "string" or not dest_dir) |
| 21 | 21 | ||
| 22 | local hg_cmd = rockspec.variables.HG | 22 | local hg_cmd = rockspec.variables.HG |
diff --git a/src/luarocks/fetch/sscm.lua b/src/luarocks/fetch/sscm.lua index 5add10db..32bb2ecc 100644 --- a/src/luarocks/fetch/sscm.lua +++ b/src/luarocks/fetch/sscm.lua | |||
| @@ -13,7 +13,7 @@ local dir = require("luarocks.dir") | |||
| 13 | -- the fetched source tarball and the temporary directory created to | 13 | -- the fetched source tarball and the temporary directory created to |
| 14 | -- store it; or nil and an error message. | 14 | -- store it; or nil and an error message. |
| 15 | function sscm.get_sources(rockspec, extract, dest_dir) | 15 | function sscm.get_sources(rockspec, extract, dest_dir) |
| 16 | assert(type(rockspec) == "table") | 16 | assert(rockspec:type() == "rockspec") |
| 17 | assert(type(dest_dir) == "string" or not dest_dir) | 17 | assert(type(dest_dir) == "string" or not dest_dir) |
| 18 | 18 | ||
| 19 | local sscm_cmd = rockspec.variables.SSCM | 19 | local sscm_cmd = rockspec.variables.SSCM |
diff --git a/src/luarocks/fetch/svn.lua b/src/luarocks/fetch/svn.lua index 29bce1b5..ceb15350 100644 --- a/src/luarocks/fetch/svn.lua +++ b/src/luarocks/fetch/svn.lua | |||
| @@ -16,7 +16,7 @@ local util = require("luarocks.util") | |||
| 16 | -- the fetched source tarball and the temporary directory created to | 16 | -- the fetched source tarball and the temporary directory created to |
| 17 | -- store it; or nil and an error message. | 17 | -- store it; or nil and an error message. |
| 18 | function svn.get_sources(rockspec, extract, dest_dir) | 18 | function svn.get_sources(rockspec, extract, dest_dir) |
| 19 | assert(type(rockspec) == "table") | 19 | assert(rockspec:type() == "rockspec") |
| 20 | assert(type(dest_dir) == "string" or not dest_dir) | 20 | assert(type(dest_dir) == "string" or not dest_dir) |
| 21 | 21 | ||
| 22 | local svn_cmd = rockspec.variables.SVN | 22 | local svn_cmd = rockspec.variables.SVN |
diff --git a/src/luarocks/manif/writer.lua b/src/luarocks/manif/writer.lua index 8e8d5525..6f70338b 100644 --- a/src/luarocks/manif/writer.lua +++ b/src/luarocks/manif/writer.lua | |||
| @@ -275,6 +275,7 @@ function writer.make_rock_manifest(name, version) | |||
| 275 | local rock_manifest = { rock_manifest=tree } | 275 | local rock_manifest = { rock_manifest=tree } |
| 276 | manif.rock_manifest_cache[name.."/"..version] = rock_manifest | 276 | manif.rock_manifest_cache[name.."/"..version] = rock_manifest |
| 277 | save_table(install_dir, "rock_manifest", rock_manifest ) | 277 | save_table(install_dir, "rock_manifest", rock_manifest ) |
| 278 | return true | ||
| 278 | end | 279 | end |
| 279 | 280 | ||
| 280 | -- Writes a 'rock_namespace' file in a locally installed rock directory. | 281 | -- Writes a 'rock_namespace' file in a locally installed rock directory. |
diff --git a/src/luarocks/pack.lua b/src/luarocks/pack.lua index 6423de2c..cec370db 100644 --- a/src/luarocks/pack.lua +++ b/src/luarocks/pack.lua | |||
| @@ -29,7 +29,7 @@ function pack.pack_source_rock(rockspec_file) | |||
| 29 | if err then | 29 | if err then |
| 30 | return nil, "Error loading rockspec: "..err | 30 | return nil, "Error loading rockspec: "..err |
| 31 | end | 31 | end |
| 32 | rockspec_file = rockspec.local_filename | 32 | rockspec_file = rockspec.local_abs_filename |
| 33 | 33 | ||
| 34 | local name_version = rockspec.name .. "-" .. rockspec.version | 34 | local name_version = rockspec.name .. "-" .. rockspec.version |
| 35 | local rock_file = fs.absolute_name(name_version .. ".src.rock") | 35 | local rock_file = fs.absolute_name(name_version .. ".src.rock") |
diff --git a/src/luarocks/path.lua b/src/luarocks/path.lua index a8426090..8fe6da8d 100644 --- a/src/luarocks/path.lua +++ b/src/luarocks/path.lua | |||
| @@ -211,26 +211,6 @@ function path.module_to_path(mod) | |||
| 211 | return (mod:gsub("[^.]*$", ""):gsub("%.", "/")) | 211 | return (mod:gsub("[^.]*$", ""):gsub("%.", "/")) |
| 212 | end | 212 | end |
| 213 | 213 | ||
| 214 | --- Set up path-related variables for a given rock. | ||
| 215 | -- Create a "variables" table in the rockspec table, containing | ||
| 216 | -- adjusted variables according to the configuration file. | ||
| 217 | -- @param rockspec table: The rockspec table. | ||
| 218 | function path.configure_paths(rockspec) | ||
| 219 | assert(type(rockspec) == "table") | ||
| 220 | local vars = {} | ||
| 221 | for k,v in pairs(cfg.variables) do | ||
| 222 | vars[k] = v | ||
| 223 | end | ||
| 224 | local name, version = rockspec.name, rockspec.version | ||
| 225 | vars.PREFIX = path.install_dir(name, version) | ||
| 226 | vars.LUADIR = path.lua_dir(name, version) | ||
| 227 | vars.LIBDIR = path.lib_dir(name, version) | ||
| 228 | vars.CONFDIR = path.conf_dir(name, version) | ||
| 229 | vars.BINDIR = path.bin_dir(name, version) | ||
| 230 | vars.DOCDIR = path.doc_dir(name, version) | ||
| 231 | rockspec.variables = vars | ||
| 232 | end | ||
| 233 | |||
| 234 | function path.use_tree(tree) | 214 | function path.use_tree(tree) |
| 235 | cfg.root_dir = tree | 215 | cfg.root_dir = tree |
| 236 | cfg.rocks_dir = path.rocks_dir(tree) | 216 | cfg.rocks_dir = path.rocks_dir(tree) |
diff --git a/src/luarocks/remove.lua b/src/luarocks/remove.lua index 1b4e3562..9ae89da4 100644 --- a/src/luarocks/remove.lua +++ b/src/luarocks/remove.lua | |||
| @@ -30,7 +30,7 @@ local function check_dependents(name, versions, deps_mode) | |||
| 30 | for rock_version, _ in pairs(rock_versions) do | 30 | for rock_version, _ in pairs(rock_versions) do |
| 31 | local rockspec, err = fetch.load_rockspec(path.rockspec_file(rock_name, rock_version)) | 31 | local rockspec, err = fetch.load_rockspec(path.rockspec_file(rock_name, rock_version)) |
| 32 | if rockspec then | 32 | if rockspec then |
| 33 | local _, missing = deps.match_deps(rockspec, blacklist, deps_mode) | 33 | local _, missing = deps.match_deps(rockspec.dependencies, rockspec.rocks_provided, blacklist, deps_mode) |
| 34 | if missing[name] then | 34 | if missing[name] then |
| 35 | table.insert(dependents, { name = rock_name, version = rock_version }) | 35 | table.insert(dependents, { name = rock_name, version = rock_version }) |
| 36 | end | 36 | end |
diff --git a/src/luarocks/repos.lua b/src/luarocks/repos.lua index 54610489..454ec79f 100644 --- a/src/luarocks/repos.lua +++ b/src/luarocks/repos.lua | |||
| @@ -147,7 +147,7 @@ function repos.has_binaries(name, version) | |||
| 147 | end | 147 | end |
| 148 | 148 | ||
| 149 | function repos.run_hook(rockspec, hook_name) | 149 | function repos.run_hook(rockspec, hook_name) |
| 150 | assert(type(rockspec) == "table") | 150 | assert(rockspec:type() == "rockspec") |
| 151 | assert(type(hook_name) == "string") | 151 | assert(type(hook_name) == "string") |
| 152 | 152 | ||
| 153 | local hooks = rockspec.hooks | 153 | local hooks = rockspec.hooks |
| @@ -174,7 +174,7 @@ function repos.run_hook(rockspec, hook_name) | |||
| 174 | end | 174 | end |
| 175 | 175 | ||
| 176 | function repos.should_wrap_bin_scripts(rockspec) | 176 | function repos.should_wrap_bin_scripts(rockspec) |
| 177 | assert(type(rockspec) == "table") | 177 | assert(rockspec:type() == "rockspec") |
| 178 | 178 | ||
| 179 | if cfg.wrap_bin_scripts ~= nil then | 179 | if cfg.wrap_bin_scripts ~= nil then |
| 180 | return cfg.wrap_bin_scripts | 180 | return cfg.wrap_bin_scripts |
diff --git a/src/luarocks/rockspecs.lua b/src/luarocks/rockspecs.lua new file mode 100644 index 00000000..373f6caa --- /dev/null +++ b/src/luarocks/rockspecs.lua | |||
| @@ -0,0 +1,159 @@ | |||
| 1 | local rockspecs = {} | ||
| 2 | |||
| 3 | local cfg = require("luarocks.core.cfg") | ||
| 4 | local dir = require("luarocks.dir") | ||
| 5 | local path = require("luarocks.path") | ||
| 6 | local queries = require("luarocks.queries") | ||
| 7 | local type_rockspec = require("luarocks.type.rockspec") | ||
| 8 | local util = require("luarocks.core.util") | ||
| 9 | local vers = require("luarocks.core.vers") | ||
| 10 | |||
| 11 | local rockspec_mt = {} | ||
| 12 | |||
| 13 | rockspec_mt.__index = rockspec_mt | ||
| 14 | |||
| 15 | function rockspec_mt.type() | ||
| 16 | return "rockspec" | ||
| 17 | end | ||
| 18 | |||
| 19 | --- Perform platform-specific overrides on a table. | ||
| 20 | -- Overrides values of table with the contents of the appropriate | ||
| 21 | -- subset of its "platforms" field. The "platforms" field should | ||
| 22 | -- be a table containing subtables keyed with strings representing | ||
| 23 | -- platform names. Names that match the contents of the global | ||
| 24 | -- cfg.platforms setting are used. For example, if | ||
| 25 | -- cfg.platforms= {"foo"}, then the fields of | ||
| 26 | -- tbl.platforms.foo will overwrite those of tbl with the same | ||
| 27 | -- names. For table values, the operation is performed recursively | ||
| 28 | -- (tbl.platforms.foo.x.y.z overrides tbl.x.y.z; other contents of | ||
| 29 | -- tbl.x are preserved). | ||
| 30 | -- @param tbl table or nil: Table which may contain a "platforms" field; | ||
| 31 | -- if it doesn't (or if nil is passed), this function does nothing. | ||
| 32 | local function platform_overrides(tbl) | ||
| 33 | assert(type(tbl) == "table" or not tbl) | ||
| 34 | |||
| 35 | if not tbl then return end | ||
| 36 | |||
| 37 | if tbl.platforms then | ||
| 38 | for _, platform in ipairs(cfg.platforms) do | ||
| 39 | local platform_tbl = tbl.platforms[platform] | ||
| 40 | if platform_tbl then | ||
| 41 | util.deep_merge(tbl, platform_tbl) | ||
| 42 | end | ||
| 43 | end | ||
| 44 | end | ||
| 45 | tbl.platforms = nil | ||
| 46 | end | ||
| 47 | |||
| 48 | local function convert_dependencies(rockspec, key) | ||
| 49 | if rockspec[key] then | ||
| 50 | for i = 1, #rockspec[key] do | ||
| 51 | local parsed, err = queries.from_dep_string(rockspec[key][i]) | ||
| 52 | if not parsed then | ||
| 53 | return nil, "Parse error processing dependency '"..rockspec[key][i].."': "..tostring(err) | ||
| 54 | end | ||
| 55 | rockspec[key][i] = parsed | ||
| 56 | end | ||
| 57 | else | ||
| 58 | rockspec[key] = {} | ||
| 59 | end | ||
| 60 | end | ||
| 61 | |||
| 62 | --- Set up path-related variables for a given rock. | ||
| 63 | -- Create a "variables" table in the rockspec table, containing | ||
| 64 | -- adjusted variables according to the configuration file. | ||
| 65 | -- @param rockspec table: The rockspec table. | ||
| 66 | local function configure_paths(rockspec) | ||
| 67 | local vars = {} | ||
| 68 | for k,v in pairs(cfg.variables) do | ||
| 69 | vars[k] = v | ||
| 70 | end | ||
| 71 | local name, version = rockspec.name, rockspec.version | ||
| 72 | vars.PREFIX = path.install_dir(name, version) | ||
| 73 | vars.LUADIR = path.lua_dir(name, version) | ||
| 74 | vars.LIBDIR = path.lib_dir(name, version) | ||
| 75 | vars.CONFDIR = path.conf_dir(name, version) | ||
| 76 | vars.BINDIR = path.bin_dir(name, version) | ||
| 77 | vars.DOCDIR = path.doc_dir(name, version) | ||
| 78 | rockspec.variables = vars | ||
| 79 | end | ||
| 80 | |||
| 81 | function rockspecs.from_persisted_table(filename, rockspec, globals, quick) | ||
| 82 | assert(type(rockspec) == "table") | ||
| 83 | assert(type(globals) == "table" or globals == nil) | ||
| 84 | assert(type(filename) == "string") | ||
| 85 | assert(type(quick) == "boolean" or quick == nil) | ||
| 86 | |||
| 87 | if rockspec.rockspec_format then | ||
| 88 | if vers.compare_versions(rockspec.rockspec_format, type_rockspec.rockspec_format) then | ||
| 89 | return nil, "Rockspec format "..rockspec.rockspec_format.." is not supported, please upgrade LuaRocks." | ||
| 90 | end | ||
| 91 | end | ||
| 92 | |||
| 93 | if not quick then | ||
| 94 | local ok, err = type_rockspec.check(rockspec, globals or {}) | ||
| 95 | if not ok then | ||
| 96 | return nil, err | ||
| 97 | end | ||
| 98 | end | ||
| 99 | |||
| 100 | --- Check if rockspec format version satisfies version requirement. | ||
| 101 | -- @param rockspec table: The rockspec table. | ||
| 102 | -- @param version string: required version. | ||
| 103 | -- @return boolean: true if rockspec format matches version or is newer, false otherwise. | ||
| 104 | do | ||
| 105 | local parsed_format = vers.parse_version(rockspec.rockspec_format or "1.0") | ||
| 106 | rockspec.format_is_at_least = function(self, version) | ||
| 107 | return parsed_format >= vers.parse_version(version) | ||
| 108 | end | ||
| 109 | end | ||
| 110 | |||
| 111 | platform_overrides(rockspec.build) | ||
| 112 | platform_overrides(rockspec.dependencies) | ||
| 113 | platform_overrides(rockspec.build_dependencies) | ||
| 114 | platform_overrides(rockspec.test_dependencies) | ||
| 115 | platform_overrides(rockspec.external_dependencies) | ||
| 116 | platform_overrides(rockspec.source) | ||
| 117 | platform_overrides(rockspec.hooks) | ||
| 118 | platform_overrides(rockspec.test) | ||
| 119 | |||
| 120 | rockspec.name = rockspec.package:lower() | ||
| 121 | |||
| 122 | local protocol, pathname = dir.split_url(rockspec.source.url) | ||
| 123 | if dir.is_basic_protocol(protocol) then | ||
| 124 | rockspec.source.file = rockspec.source.file or dir.base_name(rockspec.source.url) | ||
| 125 | end | ||
| 126 | rockspec.source.protocol, rockspec.source.pathname = protocol, pathname | ||
| 127 | |||
| 128 | -- Temporary compatibility | ||
| 129 | if rockspec.source.cvs_module then rockspec.source.module = rockspec.source.cvs_module end | ||
| 130 | if rockspec.source.cvs_tag then rockspec.source.tag = rockspec.source.cvs_tag end | ||
| 131 | |||
| 132 | rockspec.local_abs_filename = filename | ||
| 133 | local filebase = rockspec.source.file or rockspec.source.url | ||
| 134 | local base = dir.deduce_base_dir(filebase) | ||
| 135 | rockspec.source.dir_set = rockspec.source.dir ~= nil | ||
| 136 | rockspec.source.dir = rockspec.source.dir | ||
| 137 | or rockspec.source.module | ||
| 138 | or ( (filebase:match("%.lua$") or filebase:match("%.c$")) | ||
| 139 | and (rockspec:format_is_at_least("3.0") | ||
| 140 | and (dir.is_basic_protocol(protocol) and "." or base) | ||
| 141 | or ".") ) | ||
| 142 | or base | ||
| 143 | |||
| 144 | rockspec.rocks_provided = (rockspec:format_is_at_least("3.0") | ||
| 145 | and cfg.rocks_provided_3_0 | ||
| 146 | or cfg.rocks_provided) | ||
| 147 | |||
| 148 | convert_dependencies(rockspec, "dependencies") | ||
| 149 | convert_dependencies(rockspec, "build_dependencies") | ||
| 150 | convert_dependencies(rockspec, "test_dependencies") | ||
| 151 | |||
| 152 | if not quick then | ||
| 153 | configure_paths(rockspec) | ||
| 154 | end | ||
| 155 | |||
| 156 | return setmetatable(rockspec, rockspec_mt) | ||
| 157 | end | ||
| 158 | |||
| 159 | return rockspecs \ No newline at end of file | ||
diff --git a/src/luarocks/search.lua b/src/luarocks/search.lua index 90626f3c..da527bc6 100644 --- a/src/luarocks/search.lua +++ b/src/luarocks/search.lua | |||
| @@ -221,6 +221,15 @@ local function supported_lua_versions(query) | |||
| 221 | return result_tree | 221 | return result_tree |
| 222 | end | 222 | end |
| 223 | 223 | ||
| 224 | function search.find_src_or_rockspec(ns_name, version) | ||
| 225 | local query = queries.new(ns_name, version, false, "src|rockspec") | ||
| 226 | local url, err = search.find_suitable_rock(query) | ||
| 227 | if not url then | ||
| 228 | return nil, "Could not find a result named "..tostring(query)..": "..err | ||
| 229 | end | ||
| 230 | return url | ||
| 231 | end | ||
| 232 | |||
| 224 | --- Attempt to get a single URL for a given search for a rock. | 233 | --- Attempt to get a single URL for a given search for a rock. |
| 225 | -- @param query table: a query object. | 234 | -- @param query table: a query object. |
| 226 | -- @return string or (nil, string): URL for latest matching version | 235 | -- @return string or (nil, string): URL for latest matching version |
| @@ -308,29 +317,6 @@ function search.print_result_tree(result_tree, porcelain) | |||
| 308 | end | 317 | end |
| 309 | end | 318 | end |
| 310 | 319 | ||
| 311 | --- Given a name and optionally a version, try to find in the rocks | ||
| 312 | -- servers a single .src.rock or .rockspec file that satisfies | ||
| 313 | -- the request, and run the given function on it; or display to the | ||
| 314 | -- user possibilities if it couldn't narrow down a single match. | ||
| 315 | -- @param action function: A function that takes a .src.rock or | ||
| 316 | -- .rockspec URL as a parameter. | ||
| 317 | -- @param ns_name string: A rock name, may be namespaced | ||
| 318 | -- @param version string or nil: A version number may also be given. | ||
| 319 | -- @return The result of the action function, or nil and an error message. | ||
| 320 | function search.act_on_src_or_rockspec(action, ns_name, version, ...) | ||
| 321 | assert(type(action) == "function") | ||
| 322 | assert(type(ns_name) == "string") | ||
| 323 | assert(type(version) == "string" or not version) | ||
| 324 | |||
| 325 | local query = queries.new(ns_name, version, false, "src|rockspec") | ||
| 326 | local url, err = search.find_suitable_rock(query) | ||
| 327 | if not url then | ||
| 328 | return nil, "Could not find a result named "..tostring(query)..": "..err | ||
| 329 | end | ||
| 330 | local _, namespace = util.split_namespace(ns_name) | ||
| 331 | return action(url, namespace, ...) | ||
| 332 | end | ||
| 333 | |||
| 334 | function search.pick_installed_rock(query, given_tree) | 320 | function search.pick_installed_rock(query, given_tree) |
| 335 | assert(query:type() == "query") | 321 | assert(query:type() == "query") |
| 336 | 322 | ||
diff --git a/src/luarocks/type_check.lua b/src/luarocks/type_check.lua index 9e3b7c9e..ebd59f85 100644 --- a/src/luarocks/type_check.lua +++ b/src/luarocks/type_check.lua | |||
| @@ -110,12 +110,12 @@ function type_check.type_check_table(version, tbl, typetbl, context) | |||
| 110 | assert(type(version) == "string") | 110 | assert(type(version) == "string") |
| 111 | assert(type(tbl) == "table") | 111 | assert(type(tbl) == "table") |
| 112 | assert(type(typetbl) == "table") | 112 | assert(type(typetbl) == "table") |
| 113 | 113 | ||
| 114 | local ok, err = check_version(version, typetbl, context) | 114 | local ok, err = check_version(version, typetbl, context) |
| 115 | if not ok then | 115 | if not ok then |
| 116 | return nil, err | 116 | return nil, err |
| 117 | end | 117 | end |
| 118 | 118 | ||
| 119 | for k, v in pairs(tbl) do | 119 | for k, v in pairs(tbl) do |
| 120 | local t = typetbl[k] or typetbl._any | 120 | local t = typetbl[k] or typetbl._any |
| 121 | if t then | 121 | if t then |
diff --git a/src/luarocks/util.lua b/src/luarocks/util.lua index ea18071f..cd946451 100644 --- a/src/luarocks/util.lua +++ b/src/luarocks/util.lua | |||
| @@ -215,37 +215,6 @@ function util.parse_flags(...) | |||
| 215 | return flags, unpack(out) | 215 | return flags, unpack(out) |
| 216 | end | 216 | end |
| 217 | 217 | ||
| 218 | --- Perform platform-specific overrides on a table. | ||
| 219 | -- Overrides values of table with the contents of the appropriate | ||
| 220 | -- subset of its "platforms" field. The "platforms" field should | ||
| 221 | -- be a table containing subtables keyed with strings representing | ||
| 222 | -- platform names. Names that match the contents of the global | ||
| 223 | -- cfg.platforms setting are used. For example, if | ||
| 224 | -- cfg.platforms= {"foo"}, then the fields of | ||
| 225 | -- tbl.platforms.foo will overwrite those of tbl with the same | ||
| 226 | -- names. For table values, the operation is performed recursively | ||
| 227 | -- (tbl.platforms.foo.x.y.z overrides tbl.x.y.z; other contents of | ||
| 228 | -- tbl.x are preserved). | ||
| 229 | -- @param tbl table or nil: Table which may contain a "platforms" field; | ||
| 230 | -- if it doesn't (or if nil is passed), this function does nothing. | ||
| 231 | function util.platform_overrides(tbl) | ||
| 232 | assert(type(tbl) == "table" or not tbl) | ||
| 233 | |||
| 234 | local cfg = require("luarocks.core.cfg") | ||
| 235 | |||
| 236 | if not tbl then return end | ||
| 237 | |||
| 238 | if tbl.platforms then | ||
| 239 | for _, platform in ipairs(cfg.platforms) do | ||
| 240 | local platform_tbl = tbl.platforms[platform] | ||
| 241 | if platform_tbl then | ||
| 242 | core.deep_merge(tbl, platform_tbl) | ||
| 243 | end | ||
| 244 | end | ||
| 245 | end | ||
| 246 | tbl.platforms = nil | ||
| 247 | end | ||
| 248 | |||
| 249 | local var_format_pattern = "%$%((%a[%a%d_]+)%)" | 218 | local var_format_pattern = "%$%((%a[%a%d_]+)%)" |
| 250 | 219 | ||
| 251 | -- Check if a set of needed variables are referenced | 220 | -- Check if a set of needed variables are referenced |
