From 98e9f4a233c12136d8ae1231c7e3263240cc7e4a Mon Sep 17 00:00:00 2001 From: V1K1NGbg Date: Thu, 22 Aug 2024 17:49:01 -0300 Subject: Teal: convert luarocks.cmd.install --- src/luarocks/cmd/install.lua | 274 ------------------------------------------- src/luarocks/cmd/install.tl | 259 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 259 insertions(+), 274 deletions(-) delete mode 100644 src/luarocks/cmd/install.lua create mode 100644 src/luarocks/cmd/install.tl diff --git a/src/luarocks/cmd/install.lua b/src/luarocks/cmd/install.lua deleted file mode 100644 index c3b5f811..00000000 --- a/src/luarocks/cmd/install.lua +++ /dev/null @@ -1,274 +0,0 @@ ---- Module implementing the LuaRocks "install" command. --- Installs binary rocks. -local install = {} - -local dir = require("luarocks.dir") -local path = require("luarocks.path") -local repos = require("luarocks.repos") -local fetch = require("luarocks.fetch") -local util = require("luarocks.util") -local fs = require("luarocks.fs") -local deps = require("luarocks.deps") -local writer = require("luarocks.manif.writer") -local remove = require("luarocks.remove") -local search = require("luarocks.search") -local queries = require("luarocks.queries") -local cfg = require("luarocks.core.cfg") - -function install.add_to_parser(parser) - local cmd = parser:command("install", "Install a rock.", util.see_also()) -- luacheck: ignore 431 - - cmd:argument("rock", "The name of a rock to be fetched from a repository ".. - "or a filename of a locally available rock.") - :action(util.namespaced_name_action) - cmd:argument("version", "Version of the rock.") - :args("?") - - cmd:flag("--keep", "Do not remove previously installed versions of the ".. - "rock after building a new one. This behavior can be made permanent by ".. - "setting keep_other_versions=true in the configuration file.") - cmd:flag("--force", "If --keep is not specified, force removal of ".. - "previously installed versions if it would break dependencies. ".. - "If rock is already installed, reinstall it anyway.") - cmd:flag("--force-fast", "Like --force, but performs a forced removal ".. - "without reporting dependency issues.") - cmd:flag("--only-deps --deps-only", "Install only the dependencies of the rock.") - cmd:flag("--no-doc", "Install the rock without its documentation.") - cmd:flag("--verify", "Verify signature of the rockspec or src.rock being ".. - "built. If the rockspec or src.rock is being downloaded, LuaRocks will ".. - "attempt to download the signature as well. Otherwise, the signature ".. - "file should be already available locally in the same directory.\n".. - "You need the signer’s public key in your local keyring for this ".. - "option to work properly.") - cmd:flag("--check-lua-versions", "If the rock can't be found, check repository ".. - "and report if it is available for another Lua version.") - util.deps_mode_option(cmd) - cmd:flag("--no-manifest", "Skip creating/updating the manifest") - cmd:flag("--pin", "If the installed rock is a Lua module, create a ".. - "luarocks.lock file listing the exact versions of each dependency found for ".. - "this rock (recursively), and store it in the rock's directory. ".. - "Ignores any existing luarocks.lock file in the rock's sources.") - -- luarocks build options - parser:flag("--pack-binary-rock"):hidden(true) - parser:option("--branch"):hidden(true) - parser:flag("--sign"):hidden(true) -end - -install.opts = util.opts_table("install.opts", { - namespace = "string?", - keep = "boolean", - force = "boolean", - force_fast = "boolean", - no_doc = "boolean", - deps_mode = "string", - verify = "boolean", -}) - ---- Install a binary rock. --- @param rock_file string: local or remote filename of a rock. --- @param opts table: installation options --- @return (string, string) or (nil, string, [string]): Name and version of --- installed rock if succeeded or nil and an error message followed by an error code. -function install.install_binary_rock(rock_file, opts) - assert(type(rock_file) == "string") - assert(opts:type() == "install.opts") - - local namespace = opts.namespace - local deps_mode = opts.deps_mode - - local name, version, arch = path.parse_name(rock_file) - if not name then - return nil, "Filename "..rock_file.." does not match format 'name-version-revision.arch.rock'." - end - - if arch ~= "all" and arch ~= cfg.arch then - return nil, "Incompatible architecture "..arch, "arch" - end - if repos.is_installed(name, version) then - if not (opts.force or opts.force_fast) then - util.printout(name .. " " .. version .. " is already installed in " .. path.root_dir(cfg.root_dir)) - util.printout("Use --force to reinstall.") - return name, version - end - repos.delete_version(name, version, opts.deps_mode) - end - - local install_dir = path.install_dir(name, version) - - local rollback = util.schedule_function(function() - fs.delete(install_dir) - fs.remove_dir_if_empty(path.versions_dir(name)) - end) - - local ok, err, errcode = fetch.fetch_and_unpack_rock(rock_file, install_dir, opts.verify) - if not ok then return nil, err, errcode end - - local rockspec, err = fetch.load_rockspec(path.rockspec_file(name, version)) - if err then - return nil, "Failed loading rockspec for installed package: "..err, errcode - end - - if opts.deps_mode ~= "none" then - ok, err, errcode = deps.check_external_deps(rockspec, "install") - if err then return nil, err, errcode end - end - - -- For compatibility with .rock files built with LuaRocks 1 - if not fs.exists(path.rock_manifest_file(name, version)) then - ok, err = writer.make_rock_manifest(name, version) - if err then return nil, err end - end - - if namespace then - ok, err = writer.make_namespace_file(name, version, namespace) - if err then return nil, err end - end - - if deps_mode ~= "none" then - local deplock_dir = fs.exists(dir.path(".", "luarocks.lock")) - and "." - or install_dir - ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", deps_mode, opts.verify, deplock_dir) - if err then return nil, err, errcode end - end - - ok, err = repos.deploy_files(name, version, repos.should_wrap_bin_scripts(rockspec), deps_mode) - if err then return nil, err end - - util.remove_scheduled_function(rollback) - rollback = util.schedule_function(function() - repos.delete_version(name, version, deps_mode) - end) - - ok, err = repos.run_hook(rockspec, "post_install") - if err then return nil, err end - - util.announce_install(rockspec) - util.remove_scheduled_function(rollback) - return name, version -end - ---- Installs the dependencies of a binary rock. --- @param rock_file string: local or remote filename of a rock. --- @param opts table: installation options --- @return (string, string) or (nil, string, [string]): Name and version of --- the rock whose dependencies were installed if succeeded or nil and an error message --- followed by an error code. -function install.install_binary_rock_deps(rock_file, opts) - assert(type(rock_file) == "string") - assert(opts:type() == "install.opts") - - local name, version, arch = path.parse_name(rock_file) - if not name then - return nil, "Filename "..rock_file.." does not match format 'name-version-revision.arch.rock'." - end - - if arch ~= "all" and arch ~= cfg.arch then - return nil, "Incompatible architecture "..arch, "arch" - end - - local install_dir = path.install_dir(name, version) - - local ok, err, errcode = fetch.fetch_and_unpack_rock(rock_file, install_dir, opts.verify) - if not ok then return nil, err, errcode end - - local rockspec, err = fetch.load_rockspec(path.rockspec_file(name, version)) - if err then - return nil, "Failed loading rockspec for installed package: "..err, errcode - end - - local deplock_dir = fs.exists(dir.path(".", "luarocks.lock")) - and "." - or install_dir - ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", opts.deps_mode, opts.verify, deplock_dir) - if err then return nil, err, errcode end - - util.printout() - util.printout("Successfully installed dependencies for " ..name.." "..version) - - return name, version -end - -local function install_rock_file_deps(filename, opts) - assert(opts:type() == "install.opts") - - local name, version = install.install_binary_rock_deps(filename, opts) - if not name then return nil, version end - - writer.check_dependencies(nil, opts.deps_mode) - return name, version -end - -local function install_rock_file(filename, opts) - assert(type(filename) == "string") - assert(opts:type() == "install.opts") - - local name, version = install.install_binary_rock(filename, opts) - if not name then return nil, version end - - if opts.no_doc then - util.remove_doc_dir(name, version) - end - - if (not opts.keep) and not cfg.keep_other_versions then - local ok, err, warn = remove.remove_other_versions(name, version, opts.force, opts.force_fast) - if not ok then - return nil, err - elseif warn then - util.printerr(err) - end - end - - writer.check_dependencies(nil, opts.deps_mode) - return name, version -end - ---- Driver function for the "install" command. --- If an URL or pathname to a binary rock is given, fetches and installs it. --- If a rockspec or a source rock is given, forwards the request to the "build" --- command. --- If a package name is given, forwards the request to "search" and, --- if returned a result, installs the matching rock. --- @return boolean or (nil, string, exitcode): True if installation was --- successful, nil and an error message otherwise. exitcode is optionally returned. -function install.command(args) - if args.rock:match("%.rockspec$") or args.rock:match("%.src%.rock$") then - local build = require("luarocks.cmd.build") - return build.command(args) - elseif args.rock:match("%.rock$") then - local deps_mode = deps.get_deps_mode(args) - local opts = install.opts({ - namespace = args.namespace, - keep = not not args.keep, - force = not not args.force, - force_fast = not not args.force_fast, - no_doc = not not args.no_doc, - deps_mode = deps_mode, - verify = not not args.verify, - }) - if args.only_deps then - return install_rock_file_deps(args.rock, opts) - else - return install_rock_file(args.rock, opts) - end - else - local url, err = search.find_rock_checking_lua_versions( - queries.new(args.rock, args.namespace, args.version), - args.check_lua_versions) - if not url then - return nil, err - end - util.printout("Installing "..url) - args.rock = url - return install.command(args) - end -end - -install.needs_lock = function(args) - if args.pack_binary_rock then - return false - end - return true -end - -return install diff --git a/src/luarocks/cmd/install.tl b/src/luarocks/cmd/install.tl new file mode 100644 index 00000000..943afdba --- /dev/null +++ b/src/luarocks/cmd/install.tl @@ -0,0 +1,259 @@ +--- Module implementing the LuaRocks "install" command. +-- Installs binary rocks. +local record install + needs_lock: function(Args): boolean +end + +local dir = require("luarocks.dir") +local path = require("luarocks.path") +local repos = require("luarocks.repos") +local fetch = require("luarocks.fetch") +local util = require("luarocks.util") +local fs = require("luarocks.fs") +local deps = require("luarocks.deps") +local repo_writer = require("luarocks.repo_writer") +local remove = require("luarocks.remove") +local search = require("luarocks.search") +local queries = require("luarocks.queries") +local cfg = require("luarocks.core.cfg") + +local type Parser = require("luarocks.vendor.argparse").Parser + +local type Args = require("luarocks.core.types.args").Args + + +local type IOpts = require("luarocks.core.types.installs").IOpts + +function install.add_to_parser(parser: Parser) + local cmd = parser:command("install", "Install a rock.", util.see_also()) -- luacheck: ignore 431 + + cmd:argument("rock", "The name of a rock to be fetched from a repository ".. + "or a filename of a locally available rock.") + :action(util.namespaced_name_action) + cmd:argument("version", "Version of the rock.") + :args("?") + + cmd:flag("--keep", "Do not remove previously installed versions of the ".. + "rock after building a new one. This behavior can be made permanent by ".. + "setting keep_other_versions=true in the configuration file.") + cmd:flag("--force", "If --keep is not specified, force removal of ".. + "previously installed versions if it would break dependencies. ".. + "If rock is already installed, reinstall it anyway.") + cmd:flag("--force-fast", "Like --force, but performs a forced removal ".. + "without reporting dependency issues.") + cmd:flag("--only-deps --deps-only", "Install only the dependencies of the rock.") + cmd:flag("--no-doc", "Install the rock without its documentation.") + cmd:flag("--verify", "Verify signature of the rockspec or src.rock being ".. + "built. If the rockspec or src.rock is being downloaded, LuaRocks will ".. + "attempt to download the signature as well. Otherwise, the signature ".. + "file should be already available locally in the same directory.\n".. + "You need the signer’s public key in your local keyring for this ".. + "option to work properly.") + cmd:flag("--check-lua-versions", "If the rock can't be found, check repository ".. + "and report if it is available for another Lua version.") + util.deps_mode_option(cmd as Parser) + cmd:flag("--no-manifest", "Skip creating/updating the manifest") + cmd:flag("--pin", "If the installed rock is a Lua module, create a ".. + "luarocks.lock file listing the exact versions of each dependency found for ".. + "this rock (recursively), and store it in the rock's directory. ".. + "Ignores any existing luarocks.lock file in the rock's sources.") + -- luarocks build options + parser:flag("--pack-binary-rock"):hidden(true) + parser:option("--branch"):hidden(true) + parser:flag("--sign"):hidden(true) +end + + +--- Install a binary rock. +-- @param rock_file string: local or remote filename of a rock. +-- @param opts table: installation options +-- @return (string, string) or (nil, string, [string]): Name and version of +-- installed rock if succeeded or nil and an error message followed by an error code. +function install.install_binary_rock(rock_file: string, opts: IOpts): string, string, string + + local namespace = opts.namespace + local deps_mode = opts.deps_mode + + local name, version, arch = path.parse_name(rock_file) + if not name then + return nil, "Filename "..rock_file.." does not match format 'name-version-revision.arch.rock'." + end + + if arch ~= "all" and arch ~= cfg.arch then + return nil, "Incompatible architecture "..arch, "arch" + end + if repos.is_installed(name, version) then + if not (opts.force or opts.force_fast) then + util.printout(name .. " " .. version .. " is already installed in " .. path.root_dir(cfg.root_dir)) + util.printout("Use --force to reinstall.") + return name, version + end + repo_writer.delete_version(name, version, opts.deps_mode) + end + + local install_dir = path.install_dir(name, version) + + local rollback = util.schedule_function(function() + fs.delete(install_dir) + fs.remove_dir_if_empty(path.versions_dir(name)) + end) + local ok: boolean + local oks, err, errcode = fetch.fetch_and_unpack_rock(rock_file, install_dir, opts.verify) + if not oks then return nil, err, errcode end + + local rockspec, err = fetch.load_rockspec(path.rockspec_file(name, version)) + if err then + return nil, "Failed loading rockspec for installed package: "..err, errcode + end + + if opts.deps_mode ~= "none" then + ok, err, errcode = deps.check_external_deps(rockspec, "install") + if err then return nil, err, errcode end + end + + if deps_mode ~= "none" then + local deplock_dir = fs.exists(dir.path(".", "luarocks.lock")) + and "." + or install_dir + ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", deps_mode, opts.verify, deplock_dir) + if err then return nil, err, errcode end + end + + ok, err = repo_writer.deploy_files(name, version, repos.should_wrap_bin_scripts(rockspec), deps_mode, namespace) + if err then return nil, err end + + util.remove_scheduled_function(rollback) + rollback = util.schedule_function(function() + repo_writer.delete_version(name, version, deps_mode) + end) + + ok, err = repos.run_hook(rockspec, "post_install") + if err then return nil, err end + + util.announce_install(rockspec) + util.remove_scheduled_function(rollback) + return name, version +end + +--- Installs the dependencies of a binary rock. +-- @param rock_file string: local or remote filename of a rock. +-- @param opts table: installation options +-- @return (string, string) or (nil, string, [string]): Name and version of +-- the rock whose dependencies were installed if succeeded or nil and an error message +-- followed by an error code. +function install.install_binary_rock_deps(rock_file: string, opts: IOpts): string, string, string + + local name, version, arch = path.parse_name(rock_file) + if not name then + return nil, "Filename "..rock_file.." does not match format 'name-version-revision.arch.rock'." + end + + if arch ~= "all" and arch ~= cfg.arch then + return nil, "Incompatible architecture "..arch, "arch" + end + + local install_dir = path.install_dir(name, version) + + local ok: boolean + local oks, err, errcode = fetch.fetch_and_unpack_rock(rock_file, install_dir, opts.verify) + if not oks then return nil, err, errcode end + + local rockspec, err = fetch.load_rockspec(path.rockspec_file(name, version)) + if err then + return nil, "Failed loading rockspec for installed package: "..err, errcode + end + + local deplock_dir = fs.exists(dir.path(".", "luarocks.lock")) + and "." + or install_dir + ok, err, errcode = deps.fulfill_dependencies(rockspec, "dependencies", opts.deps_mode, opts.verify, deplock_dir) + if err then return nil, err, errcode end + + util.printout() + util.printout("Successfully installed dependencies for " ..name.." "..version) + + return name, version +end + +local function install_rock_file_deps(filename: string, opts: IOpts): boolean, string + + local name, version = install.install_binary_rock_deps(filename, opts) + if not name then return nil, version end + + deps.check_dependencies(nil, opts.deps_mode) + return true +end + +local function install_rock_file(filename: string, opts: IOpts): boolean, string + + local name, version = install.install_binary_rock(filename, opts) + if not name then return nil, version end + + if opts.no_doc then + util.remove_doc_dir(name, version) + end + + if (not opts.keep) and not cfg.keep_other_versions then + local ok, err, warn = remove.remove_other_versions(name, version, opts.force, opts.force_fast) + if not ok then + return nil, err + elseif warn then + util.printerr(err) + end + end + + deps.check_dependencies(nil, opts.deps_mode) + return true +end + +--- Driver function for the "install" command. +-- If an URL or pathname to a binary rock is given, fetches and installs it. +-- If a rockspec or a source rock is given, forwards the request to the "build" +-- command. +-- If a package name is given, forwards the request to "search" and, +-- if returned a result, installs the matching rock. +-- @return boolean or (nil, string, exitcode): True if installation was +-- successful, nil and an error message otherwise. exitcode is optionally returned. +function install.command(args: Args): boolean, string, string + if args.rock:match("%.rockspec$") or args.rock:match("%.src%.rock$") then + local build = require("luarocks.cmd.build") + return build.command(args) + elseif args.rock:match("%.rock$") then + local deps_mode = deps.get_deps_mode(args) + local opts = { + namespace = args.namespace, + keep = not not args.keep, + force = not not args.force, + force_fast = not not args.force_fast, + no_doc = not not args.no_doc, + deps_mode = deps_mode, + verify = not not args.verify, + } + if args.only_deps then + return install_rock_file_deps(args.rock, opts) + else + return install_rock_file(args.rock, opts) + end + else + local url, err = search.find_rock_checking_lua_versions( + queries.new(args.rock, args.namespace, args.version), + args.check_lua_versions) + if not url then + return nil, err + end + util.printout("Installing "..url) + args.rock = url + return install.command(args) + end +end + +install.needs_lock = function(args: Args): boolean + if args.pack_binary_rock then + return false + end + return true +end + +deps.installer = install.command + +return install -- cgit v1.2.3-55-g6feb