aboutsummaryrefslogtreecommitdiffstats
path: root/lua/nvim-lsp-installer/installers
diff options
context:
space:
mode:
Diffstat (limited to 'lua/nvim-lsp-installer/installers')
-rw-r--r--lua/nvim-lsp-installer/installers/cargo.lua69
-rw-r--r--lua/nvim-lsp-installer/installers/composer.lua90
-rw-r--r--lua/nvim-lsp-installer/installers/context.lua285
-rw-r--r--lua/nvim-lsp-installer/installers/dotnet.lua58
-rw-r--r--lua/nvim-lsp-installer/installers/gem.lua65
-rw-r--r--lua/nvim-lsp-installer/installers/go.lua54
-rw-r--r--lua/nvim-lsp-installer/installers/init.lua186
-rw-r--r--lua/nvim-lsp-installer/installers/npm.lua131
-rw-r--r--lua/nvim-lsp-installer/installers/opam.lua60
-rw-r--r--lua/nvim-lsp-installer/installers/pip3.lua91
-rw-r--r--lua/nvim-lsp-installer/installers/shell.lua117
-rw-r--r--lua/nvim-lsp-installer/installers/std.lua344
12 files changed, 0 insertions, 1550 deletions
diff --git a/lua/nvim-lsp-installer/installers/cargo.lua b/lua/nvim-lsp-installer/installers/cargo.lua
deleted file mode 100644
index 0413b637..00000000
--- a/lua/nvim-lsp-installer/installers/cargo.lua
+++ /dev/null
@@ -1,69 +0,0 @@
-require "nvim-lsp-installer.notify"(
- (
- "%s has been deprecated. See https://github.com/williamboman/nvim-lsp-installer/wiki/Async-infrastructure-changes-notice"
- ):format "nvim-lsp-installer.installers.cargo",
- vim.log.levels.WARN
-)
-
-local process = require "nvim-lsp-installer.process"
-local path = require "nvim-lsp-installer.path"
-
-local M = {}
-
----@param crate string The crate to install.
----@param opts {git:boolean, features:string|nil}
-function M.crate(crate, opts)
- ---@type ServerInstallerFunction
- return function(_, callback, ctx)
- opts = opts or {}
- local args = { "install", "--root", ".", "--locked" }
-
- if ctx.requested_server_version then
- vim.list_extend(args, { "--version", ctx.requested_server_version })
- end
-
- if opts.features then
- vim.list_extend(args, { "--features", opts.features })
- end
-
- if opts.git then
- vim.list_extend(args, { "--git", crate })
- else
- vim.list_extend(args, { crate })
- end
-
- ctx.receipt:with_primary_source(ctx.receipt.cargo(crate))
-
- process.spawn("cargo", {
- args = args,
- cwd = ctx.install_dir,
- stdio_sink = ctx.stdio_sink,
- }, callback)
- end
-end
-
----@param opts {path:string|nil}
-function M.install(opts)
- ---@type ServerInstallerFunction
- return function(_, callback, ctx)
- opts = opts or {}
- local args = { "install", "--root", "." }
- if opts.path then
- vim.list_extend(args, { "--path", opts.path })
- end
- process.spawn("cargo", {
- args = args,
- cwd = ctx.install_dir,
- stdio_sink = ctx.stdio_sink,
- }, callback)
- end
-end
-
----@param root_dir string The directory to resolve the executable from.
-function M.env(root_dir)
- return {
- PATH = process.extend_path { path.concat { root_dir, "bin" } },
- }
-end
-
-return M
diff --git a/lua/nvim-lsp-installer/installers/composer.lua b/lua/nvim-lsp-installer/installers/composer.lua
deleted file mode 100644
index 6d60e0b1..00000000
--- a/lua/nvim-lsp-installer/installers/composer.lua
+++ /dev/null
@@ -1,90 +0,0 @@
-require "nvim-lsp-installer.notify"(
- (
- "%s has been deprecated. See https://github.com/williamboman/nvim-lsp-installer/wiki/Async-infrastructure-changes-notice"
- ):format "nvim-lsp-installer.installers.composer",
- vim.log.levels.WARN
-)
-
-local installers = require "nvim-lsp-installer.installers"
-local std = require "nvim-lsp-installer.installers.std"
-local platform = require "nvim-lsp-installer.platform"
-local process = require "nvim-lsp-installer.process"
-local fs = require "nvim-lsp-installer.fs"
-local path = require "nvim-lsp-installer.path"
-local Data = require "nvim-lsp-installer.data"
-
-local list_copy = Data.list_copy
-
-local M = {}
-
-M.composer_cmd = platform.is_win and "composer.bat" or "composer"
-
----@param installer ServerInstallerFunction
-local function ensure_composer(installer)
- return installers.pipe {
- std.ensure_executables {
- { "php", "php was not found in path. Refer to https://www.php.net/." },
- { M.composer_cmd, "composer was not found in path. Refer to https://getcomposer.org/download/." },
- },
- installer,
- }
-end
-
----@param packages string[] The composer packages to install. The first item in this list will be the recipient of the server version, should the user request a specific one.
-function M.require(packages)
- return ensure_composer(
- ---@type ServerInstallerFunction
- function(_, callback, ctx)
- local pkgs = list_copy(packages)
- local c = process.chain {
- cwd = ctx.install_dir,
- stdio_sink = ctx.stdio_sink,
- }
-
- ctx.receipt:with_primary_source(ctx.receipt.composer(pkgs[1]))
- for i = 2, #pkgs do
- ctx.receipt:with_secondary_source(ctx.receipt.composer(pkgs[i]))
- end
-
- if not (fs.file_exists(path.concat { ctx.install_dir, "composer.json" })) then
- c.run(M.composer_cmd, { "init", "--no-interaction", "--stability=stable" })
- end
-
- if ctx.requested_server_version then
- -- The "head" package is the recipient for the requested version. It's.. by design... don't ask.
- pkgs[1] = ("%s:%s"):format(pkgs[1], ctx.requested_server_version)
- end
-
- c.run(M.composer_cmd, vim.list_extend({ "require" }, pkgs))
- c.spawn(callback)
- end
- )
-end
-
-function M.install()
- return ensure_composer(
- ---@type ServerInstallerFunction
- function(_, callback, ctx)
- process.spawn(M.composer_cmd, {
- args = {
- "install",
- "--no-interaction",
- "--no-dev",
- "--optimize-autoloader",
- "--classmap-authoritative",
- },
- cwd = ctx.install_dir,
- stdio_sink = ctx.stdio_sink,
- }, callback)
- end
- )
-end
-
----@param root_dir string The directory to resolve the executable from.
-function M.env(root_dir)
- return {
- PATH = process.extend_path { path.concat { root_dir, "vendor", "bin" } },
- }
-end
-
-return M
diff --git a/lua/nvim-lsp-installer/installers/context.lua b/lua/nvim-lsp-installer/installers/context.lua
deleted file mode 100644
index 14789959..00000000
--- a/lua/nvim-lsp-installer/installers/context.lua
+++ /dev/null
@@ -1,285 +0,0 @@
-require "nvim-lsp-installer.notify"(
- (
- "%s has been deprecated. See https://github.com/williamboman/nvim-lsp-installer/wiki/Async-infrastructure-changes-notice"
- ):format "nvim-lsp-installer.installers.context",
- vim.log.levels.WARN
-)
-
-local a = require "nvim-lsp-installer.core.async"
-local log = require "nvim-lsp-installer.log"
-local process = require "nvim-lsp-installer.process"
-local installers = require "nvim-lsp-installer.installers"
-local platform = require "nvim-lsp-installer.platform"
-local fs = require "nvim-lsp-installer.fs"
-local path = require "nvim-lsp-installer.path"
-local github_client = require "nvim-lsp-installer.core.managers.github.client"
-
-local M = {}
-
----@param repo string @The GitHub repo ("username/repo").
-function M.use_github_latest_tag(repo)
- ---@type ServerInstallerFunction
- return function(_, callback, context)
- context.github_repo = repo
- if context.requested_server_version then
- log.fmt_debug(
- "Requested server version already provided (%s), skipping fetching tags from GitHub.",
- context.requested_server_version
- )
- -- User has already provided a version - don't fetch the tags from GitHub
- return callback(true)
- end
- context.stdio_sink.stdout "Fetching tags from GitHub API...\n"
- a.run(github_client.fetch_latest_tag, function(success, result)
- if not success then
- context.stdio_sink.stderr(tostring(result) .. "\n")
- return callback(false)
- end
- result
- :on_success(function(latest_tag)
- context.requested_server_version = latest_tag.name
- callback(true)
- end)
- :on_failure(function(failure)
- context.stdio_sink.stderr(tostring(failure) .. "\n")
- callback(false)
- end)
- end, repo)
- end
-end
-
----@param repo string @The GitHub repo ("username/repo").
----@param opts FetchLatestGithubReleaseOpts|nil
-function M.use_github_release(repo, opts)
- opts = opts or {}
- ---@type ServerInstallerFunction
- return function(_, callback, context)
- context.github_repo = repo
- if context.requested_server_version then
- log.fmt_debug(
- "Requested server version already provided (%s), skipping fetching latest release from GitHub.",
- context.requested_server_version
- )
- -- User has already provided a version - don't fetch the latest version from GitHub
- return callback(true)
- end
- context.stdio_sink.stdout "Fetching latest release version from GitHub API...\n"
- a.run(github_client.fetch_latest_release, function(success, result)
- if not success then
- context.stdio_sink.stderr(tostring(result) .. "\n")
- return callback(false)
- end
- result
- :on_success(function(latest_release)
- context.requested_server_version = latest_release.tag_name
- callback(true)
- end)
- :on_failure(function(failure)
- context.stdio_sink.stderr(tostring(failure) .. "\n")
- callback(false)
- end)
- end, repo, opts)
- end
-end
-
----@param repo string @The GitHub report ("username/repo").
----@param file string|fun(resolved_version: string): string @The name of a file available in the provided repo's GitHub releases.
----@param opts FetchLatestGithubReleaseOpts
-function M.use_github_release_file(repo, file, opts)
- return installers.pipe {
- M.use_github_release(repo, opts),
- function(server, callback, context)
- local function get_download_url(version)
- local target_file
- if type(file) == "function" then
- target_file = file(version)
- else
- target_file = file
- end
- if not target_file then
- log.fmt_error(
- "Unable to find which release file to download. server_name=%s, repo=%s",
- server.name,
- repo
- )
- context.stdio_sink.stderr(
- (
- "Could not find which release file to download. Most likely the current operating system, architecture (%s), or libc (%s) is not supported.\n"
- ):format(platform.arch, platform.get_libc())
- )
- return nil
- end
-
- return ("https://github.com/%s/releases/download/%s/%s"):format(repo, version, target_file)
- end
-
- local download_url = get_download_url(context.requested_server_version)
- if not download_url then
- return callback(false)
- end
- context.github_release_file = download_url
- callback(true)
- end,
- }
-end
-
----Creates an installer that moves the current installation directory to the server's root directory.
-function M.promote_install_dir()
- ---@type ServerInstallerFunction
- return vim.schedule_wrap(function(server, callback, context)
- if server:promote_install_dir(context.install_dir) then
- context.install_dir = server.root_dir
- callback(true)
- else
- context.stdio_sink.stderr(
- ("Failed to promote temporary install directory to %s.\n"):format(server.root_dir)
- )
- callback(false)
- end
- end)
-end
-
----Access the context ojbect to create a new installer.
----@param fn fun(context: ServerInstallContext): ServerInstallerFunction
-function M.capture(fn)
- ---@type ServerInstallerFunction
- return function(server, callback, context)
- local installer = fn(context)
- installer(server, callback, context)
- end
-end
-
----@param fn fun(receipt_builder: InstallReceiptBuilder, ctx: ServerInstallContext)
-function M.receipt(fn)
- return M.capture(function(ctx)
- fn(ctx.receipt, ctx)
- return installers.noop
- end)
-end
-
----Update the context object.
----@param fn fun(context: ServerInstallContext): ServerInstallerFunction
-function M.set(fn)
- ---@type ServerInstallerFunction
- return function(_, callback, context)
- fn(context)
- callback(true)
- end
-end
-
----@param rel_path string @The relative path from the current installation working directory.
-function M.set_working_dir(rel_path)
- ---@type ServerInstallerFunction
- return vim.schedule_wrap(function(server, callback, context)
- local new_dir = path.concat { context.install_dir, rel_path }
- log.fmt_debug(
- "Changing installation working directory for %s from %s to %s",
- server.name,
- context.install_dir,
- new_dir
- )
- if not fs.dir_exists(new_dir) then
- local ok = pcall(fs.mkdirp, new_dir)
- if not ok then
- context.stdio_sink.stderr(("Failed to create directory %s.\n"):format(new_dir))
- return callback(false)
- end
- end
- context.install_dir = new_dir
- callback(true)
- end)
-end
-
-function M.use_os_distribution()
- ---Parses the provided contents of an /etc/\*-release file and identifies the Linux distribution.
- ---@param contents string @The contents of a /etc/\*-release file.
- ---@return table<string, any>
- local function parse_linux_dist(contents)
- local lines = vim.split(contents, "\n")
-
- local entries = {}
-
- for i = 1, #lines do
- local line = lines[i]
- local index = line:find "="
- if index then
- local key = line:sub(1, index - 1)
- local value = line:sub(index + 1)
- entries[key] = value
- end
- end
-
- if entries.ID == "ubuntu" then
- -- Parses the Ubuntu OS VERSION_ID into their version components, e.g. "18.04" -> {major=18, minor=04}
- local version_id = entries.VERSION_ID:gsub([["]], "")
- local version_parts = vim.split(version_id, "%.")
- local major = tonumber(version_parts[1])
- local minor = tonumber(version_parts[2])
-
- return {
- id = "ubuntu",
- version_id = version_id,
- version = { major = major, minor = minor },
- }
- else
- return {
- id = "linux-generic",
- }
- end
- end
-
- return installers.when {
- ---@type ServerInstallerFunction
- linux = function(_, callback, ctx)
- local stdio = process.in_memory_sink()
- process.spawn("bash", {
- args = { "-c", "cat /etc/*-release" },
- stdio_sink = stdio.sink,
- }, function(success)
- if success then
- ctx.os_distribution = parse_linux_dist(table.concat(stdio.buffers.stdout, ""))
- callback(true)
- else
- ctx.os_distribution = {
- id = "linux-generic",
- }
- callback(true)
- end
- end)
- end,
- mac = function(_, callback, ctx)
- ctx.os_distribution = {
- id = "macOS",
- }
- callback(true)
- end,
- win = function(_, callback, ctx)
- ctx.os_distribution = {
- id = "windows",
- }
- callback(true)
- end,
- }
-end
-
-function M.use_homebrew_prefix()
- return installers.on {
- mac = function(_, callback, ctx)
- local stdio = process.in_memory_sink()
- process.spawn("brew", {
- args = { "--prefix" },
- stdio_sink = stdio.sink,
- }, function(success)
- if success then
- ctx.homebrew_prefix = vim.trim(table.concat(stdio.buffers.stdout, ""))
- callback(true)
- else
- ctx.stdio_sink.stderr "Failed to locate Homebrew installation.\n"
- callback(false)
- end
- end)
- end,
- }
-end
-
-return M
diff --git a/lua/nvim-lsp-installer/installers/dotnet.lua b/lua/nvim-lsp-installer/installers/dotnet.lua
deleted file mode 100644
index 2c09aed4..00000000
--- a/lua/nvim-lsp-installer/installers/dotnet.lua
+++ /dev/null
@@ -1,58 +0,0 @@
-require "nvim-lsp-installer.notify"(
- (
- "%s has been deprecated. See https://github.com/williamboman/nvim-lsp-installer/wiki/Async-infrastructure-changes-notice"
- ):format "nvim-lsp-installer.installers.dotnet",
- vim.log.levels.WARN
-)
-
-local installers = require "nvim-lsp-installer.installers"
-local std = require "nvim-lsp-installer.installers.std"
-local process = require "nvim-lsp-installer.process"
-
-local M = {}
-
----@param installer ServerInstallerFunction
-local function ensure_dotnet(installer)
- return installers.pipe {
- std.ensure_executables {
- {
- "dotnet",
- "dotnet was not found in path. Refer to https://dotnet.microsoft.com/download for installation instructions.",
- },
- },
- installer,
- }
-end
-
----@param package string
-function M.package(package)
- return ensure_dotnet(
- ---@type ServerInstallerFunction
- function(_, callback, ctx)
- local args = {
- "tool",
- "update",
- "--tool-path",
- ".",
- }
- if ctx.requested_server_version then
- vim.list_extend(args, { "--version", ctx.requested_server_version })
- end
- vim.list_extend(args, { package })
- process.spawn("dotnet", {
- args = args,
- cwd = ctx.install_dir,
- stdio_sink = ctx.stdio_sink,
- }, callback)
- ctx.receipt:with_primary_source(ctx.receipt.dotnet(package))
- end
- )
-end
-
-function M.env(root_dir)
- return {
- PATH = process.extend_path { root_dir },
- }
-end
-
-return M
diff --git a/lua/nvim-lsp-installer/installers/gem.lua b/lua/nvim-lsp-installer/installers/gem.lua
deleted file mode 100644
index c8d03298..00000000
--- a/lua/nvim-lsp-installer/installers/gem.lua
+++ /dev/null
@@ -1,65 +0,0 @@
-require "nvim-lsp-installer.notify"(
- (
- "%s has been deprecated. See https://github.com/williamboman/nvim-lsp-installer/wiki/Async-infrastructure-changes-notice"
- ):format "nvim-lsp-installer.installers.gem",
- vim.log.levels.WARN
-)
-
-local path = require "nvim-lsp-installer.path"
-local Data = require "nvim-lsp-installer.data"
-local process = require "nvim-lsp-installer.process"
-local installers = require "nvim-lsp-installer.installers"
-local std = require "nvim-lsp-installer.installers.std"
-local platform = require "nvim-lsp-installer.platform"
-
-local M = {}
-
-M.gem_cmd = platform.is_win and "gem.cmd" or "gem"
-
----@param packages string[] @The Gem packages to install. The first item in this list will be the recipient of the server version, should the user request a specific one.
-function M.packages(packages)
- return installers.pipe {
- std.ensure_executables {
- { "ruby", "ruby was not found in path, refer to https://wiki.openstack.org/wiki/RubyGems." },
- { "gem", "gem was not found in path, refer to https://wiki.openstack.org/wiki/RubyGems." },
- },
- ---@type ServerInstallerFunction
- function(_, callback, ctx)
- local pkgs = Data.list_copy(packages or {})
-
- ctx.receipt:with_primary_source(ctx.receipt.gem(pkgs[1]))
- for i = 2, #pkgs do
- ctx.receipt:with_secondary_source(ctx.receipt.gem(pkgs[i]))
- end
-
- if ctx.requested_server_version then
- -- The "head" package is the recipient for the requested version. It's.. by design... don't ask.
- pkgs[1] = ("%s:%s"):format(pkgs[1], ctx.requested_server_version)
- end
-
- process.spawn(M.gem_cmd, {
- args = {
- "install",
- "--no-user-install",
- "--install-dir=.",
- "--bindir=bin",
- "--no-document",
- table.concat(pkgs, " "),
- },
- cwd = ctx.install_dir,
- stdio_sink = ctx.stdio_sink,
- }, callback)
- end,
- }
-end
-
----@param root_dir string
-function M.env(root_dir)
- return {
- GEM_HOME = root_dir,
- GEM_PATH = root_dir,
- PATH = process.extend_path { path.concat { root_dir, "bin" } },
- }
-end
-
-return M
diff --git a/lua/nvim-lsp-installer/installers/go.lua b/lua/nvim-lsp-installer/installers/go.lua
deleted file mode 100644
index 89d09f5f..00000000
--- a/lua/nvim-lsp-installer/installers/go.lua
+++ /dev/null
@@ -1,54 +0,0 @@
-require "nvim-lsp-installer.notify"(
- (
- "%s has been deprecated. See https://github.com/williamboman/nvim-lsp-installer/wiki/Async-infrastructure-changes-notice"
- ):format "nvim-lsp-installer.installers.go",
- vim.log.levels.WARN
-)
-
-local std = require "nvim-lsp-installer.installers.std"
-local installers = require "nvim-lsp-installer.installers"
-local process = require "nvim-lsp-installer.process"
-
-local M = {}
-
----@param packages string[] The Go packages to install. The first item in this list will be the recipient of the server version, should the user request a specific one.
-function M.packages(packages)
- return installers.pipe {
- std.ensure_executables { { "go", "go was not found in path, refer to https://golang.org/doc/install." } },
- ---@type ServerInstallerFunction
- function(_, callback, ctx)
- local c = process.chain {
- env = process.graft_env {
- GOBIN = ctx.install_dir,
- },
- cwd = ctx.install_dir,
- stdio_sink = ctx.stdio_sink,
- }
-
- -- Install the head package
- do
- local head_package = packages[1]
- ctx.receipt:with_primary_source(ctx.receipt.go(head_package))
- local version = ctx.requested_server_version or "latest"
- c.run("go", { "install", "-v", ("%s@%s"):format(head_package, version) })
- end
-
- -- Install secondary packages
- for i = 2, #packages do
- local package = packages[i]
- ctx.receipt:with_secondary_source(ctx.receipt.go(package))
- c.run("go", { "install", "-v", ("%s@latest"):format(package) })
- end
-
- c.spawn(callback)
- end,
- }
-end
-
-function M.env(root_dir)
- return {
- PATH = process.extend_path { root_dir },
- }
-end
-
-return M
diff --git a/lua/nvim-lsp-installer/installers/init.lua b/lua/nvim-lsp-installer/installers/init.lua
deleted file mode 100644
index cfe48faa..00000000
--- a/lua/nvim-lsp-installer/installers/init.lua
+++ /dev/null
@@ -1,186 +0,0 @@
-local platform = require "nvim-lsp-installer.platform"
-local log = require "nvim-lsp-installer.log"
-local Data = require "nvim-lsp-installer.data"
-
-local M = {}
-
----@param installer ServerInstallerFunction[]|ServerInstallerFunction
----@return ServerInstallerFunction
-local function normalize_installer(installer)
- if type(installer) == "table" then
- return M.pipe(installer)
- else
- return installer
- end
-end
-
----@alias ServerInstallCallback fun(success: boolean)
-
----@class ServerInstallContext
----@field receipt InstallReceiptBuilder
----@field requested_server_version string|nil @The version requested by the user.
----@field stdio_sink StdioSink
----@field github_release_file string|nil @Only available if context.use_github_release_file has been called.
----@field github_repo string|nil @Only available if context.use_github_release_file has been called.
----@field os_distribution table<string, any> @Only available if context.use_os_distribution has been called.
----@field homebrew_prefix string @Only available if context.use_homebrew_prefix has been called.
----@field install_dir string
-
----@alias ServerInstallerFunction fun(server: Server, callback: ServerInstallCallback, context: ServerInstallContext)
-
---- Composes multiple installer functions into one.
----@param installers ServerInstallerFunction[]
----@return ServerInstallerFunction
-function M.pipe(installers)
- if #installers == 0 then
- error "No installers to pipe."
- end
-
- return function(server, callback, context)
- local function execute(idx)
- local ok, err = pcall(
- installers[idx],
- server,
- vim.schedule_wrap(function(success)
- if not success then
- -- oh no, error. exit early
- callback(success)
- elseif installers[idx + 1] then
- -- iterate
- execute(idx + 1)
- else
- -- we done
- callback(success)
- end
- end),
- context
- )
- if not ok then
- context.stdio_sink.stderr(tostring(err) .. "\n")
- callback(false)
- end
- end
-
- execute(1)
- end
-end
-
---- Composes multiple installer function into one - in reversed order.
----@param installers ServerInstallerFunction[]
-function M.compose(installers)
- return M.pipe(Data.list_reverse(installers))
-end
-
----@param installers ServerInstallerFunction[]
----@return ServerInstallerFunction @An installer function that will serially execute the provided installers, until the first one succeeds.
-function M.first_successful(installers)
- if #installers == 0 then
- error "No installers to pipe."
- end
-
- return function(server, callback, context)
- local function execute(idx)
- log.fmt_trace("Executing installer idx=%d", idx)
- local ok, err = pcall(installers[idx], server, function(success)
- log.fmt_trace("Installer idx=%d on exit with success=%s", idx, success)
- if not success and installers[idx + 1] then
- -- iterate
- execute(idx + 1)
- else
- callback(success)
- end
- end, context)
- if not ok then
- context.stdio_sink.stderr(tostring(err) .. "\n")
- if installers[idx + 1] then
- execute(idx + 1)
- else
- callback(false)
- end
- end
- end
-
- execute(1)
- end
-end
-
---- Wraps the provided server installer to always succeeds.
----@param installer ServerInstallerFunction
----@return ServerInstallerFunction
-function M.always_succeed(installer)
- return function(server, callback, context)
- installer(server, function()
- callback(true)
- end, context)
- end
-end
-
----@param platform_table table<Platform, ServerInstallerFunction>
----@return ServerInstallerFunction | ServerInstallerFunction[] | nil
-local function get_by_platform(platform_table)
- if platform.is_mac then
- return platform_table.mac or platform_table.unix
- elseif platform.is_linux then
- return platform_table.linux or platform_table.unix
- elseif platform.is_unix then
- return platform_table.unix
- elseif platform.is_win then
- return platform_table.win
- else
- return nil
- end
-end
-
---- Creates a server installer that executes the given installer for the current platform.
---- If there is no server installer provided for the current platform, the installer will instantly exit successfully.
----@param platform_table table<Platform, ServerInstallerFunction>
----@return ServerInstallerFunction
-function M.on(platform_table)
- return function(server, callback, context)
- local installer = get_by_platform(platform_table)
- if installer then
- normalize_installer(installer)(server, callback, context)
- else
- callback(true)
- end
- end
-end
-
---- Creates a server installer that executes the given installer for the current platform.
---- If there is no server installer provided for the current platform, the installer will instantly exit with a failure.
----@param platform_table table<Platform, ServerInstallerFunction|ServerInstallerFunction[]>
----@return ServerInstallerFunction
-function M.when(platform_table)
- return function(server, callback, context)
- local installer = get_by_platform(platform_table)
- if installer then
- normalize_installer(installer)(server, callback, context)
- else
- context.stdio_sink.stderr(
- ("Current operating system is not yet supported for server %q.\n"):format(server.name)
- )
- callback(false)
- end
- end
-end
-
----@param installer ServerInstallerFunction|ServerInstallerFunction[] @The installer to execute in a new installer context.
-function M.branch_context(installer)
- ---@type ServerInstallerFunction
- return function(server, callback, ctx)
- local receipt = ctx.receipt
- -- This temporary nil assignment is done to avoid deepcopy traversing the receipt builder unnecessarily
- ctx.receipt = nil
- local new_context = vim.deepcopy(ctx)
- ctx.receipt = receipt
- new_context.receipt = receipt
- normalize_installer(installer)(server, callback, new_context)
- end
-end
-
----@type ServerInstallerFunction
-function M.noop(_, callback)
- callback(true)
-end
-
-return M
diff --git a/lua/nvim-lsp-installer/installers/npm.lua b/lua/nvim-lsp-installer/installers/npm.lua
deleted file mode 100644
index e436b0be..00000000
--- a/lua/nvim-lsp-installer/installers/npm.lua
+++ /dev/null
@@ -1,131 +0,0 @@
-require "nvim-lsp-installer.notify"(
- (
- "%s has been deprecated. See https://github.com/williamboman/nvim-lsp-installer/wiki/Async-infrastructure-changes-notice"
- ):format "nvim-lsp-installer.installers.npm",
- vim.log.levels.WARN
-)
-
-local path = require "nvim-lsp-installer.path"
-local fs = require "nvim-lsp-installer.fs"
-local Data = require "nvim-lsp-installer.data"
-local installers = require "nvim-lsp-installer.installers"
-local std = require "nvim-lsp-installer.installers.std"
-local platform = require "nvim-lsp-installer.platform"
-local process = require "nvim-lsp-installer.process"
-
-local list_copy = Data.list_copy
-
-local M = {}
-
-M.npm_command = platform.is_win and "npm.cmd" or "npm"
-
----@param installer ServerInstallerFunction
-local function ensure_npm(installer)
- return installers.pipe {
- std.ensure_executables {
- { "node", "node was not found in path. Refer to https://nodejs.org/en/." },
- {
- "npm",
- "npm was not found in path. Refer to https://docs.npmjs.com/downloading-and-installing-node-js-and-npm.",
- },
- },
- installer,
- }
-end
-
----@param standalone boolean @If true, will run `npm install` as a standalone command, with no consideration to the surrounding installer context (i.e. the requested version in context is ignored, global-style is not applied).
-local function create_installer(standalone)
- ---@param packages string[]
- return function(packages)
- return ensure_npm(
- ---@type ServerInstallerFunction
- function(_, callback, ctx)
- local pkgs = list_copy(packages or {})
- local c = process.chain {
- cwd = ctx.install_dir,
- stdio_sink = ctx.stdio_sink,
- }
-
- if not standalone then
- -- Use global-style. The reasons for this are:
- -- a) To avoid polluting the executables (aka bin-links) that npm creates.
- -- b) The installation is, after all, more similar to a "global" installation. We don't really gain
- -- any of the benefits of not using global style (e.g., deduping the dependency tree).
- --
- -- We write to .npmrc manually instead of going through npm because managing a local .npmrc file
- -- is a bit unreliable across npm versions (especially <7), so we take extra measures to avoid
- -- inadvertently polluting global npm config.
- fs.append_file(path.concat { ctx.install_dir, ".npmrc" }, "global-style=true")
-
- ctx.receipt:with_primary_source(ctx.receipt.npm(pkgs[1]))
- for i = 2, #pkgs do
- ctx.receipt:with_secondary_source(ctx.receipt.npm(pkgs[i]))
- end
- end
-
- -- stylua: ignore start
- if not (fs.dir_exists(path.concat { ctx.install_dir, "node_modules" }) or
- fs.file_exists(path.concat { ctx.install_dir, "package.json" }))
- then
- -- Create a package.json to set a boundary for where npm installs packages.
- c.run(M.npm_command, { "init", "--yes", "--scope=lsp-installer" })
- end
-
- if not standalone and ctx.requested_server_version and #pkgs > 0 then
- -- The "head" package is the recipient for the requested version. It's.. by design... don't ask.
- pkgs[1] = ("%s@%s"):format(pkgs[1], ctx.requested_server_version)
- end
-
- -- stylua: ignore end
- c.run(M.npm_command, vim.list_extend({ "install" }, pkgs))
- c.spawn(callback)
- end
- )
- end
-end
-
----Creates an installer that installs the provided packages. Will respect user's requested version.
-M.packages = create_installer(false)
-
----Creates an installer that installs the provided packages. Will NOT respect user's requested version.
----This is useful in situation where there's a need to install an auxiliary npm package.
-M.install = create_installer(true)
-
----Creates a server installer that executes the given locally installed npm executable.
----@param executable string
----@param args string[]
-function M.exec(executable, args)
- ---@type ServerInstallerFunction
- return function(_, callback, ctx)
- process.spawn(executable, {
- args = args,
- cwd = ctx.install_dir,
- stdio_sink = ctx.stdio_sink,
- env = process.graft_env(M.env(ctx.install_dir)),
- }, callback)
- end
-end
-
----Creates a server installer that runs the given script.
----@param script string @The npm script to run (npm run).
-function M.run(script)
- return ensure_npm(
- ---@type ServerInstallerFunction
- function(_, callback, ctx)
- process.spawn(M.npm_command, {
- args = { "run", script },
- cwd = ctx.install_dir,
- stdio_sink = ctx.stdio_sink,
- }, callback)
- end
- )
-end
-
----@param root_dir string @The directory to resolve the executable from.
-function M.env(root_dir)
- return {
- PATH = process.extend_path { path.concat { root_dir, "node_modules", ".bin" } },
- }
-end
-
-return M
diff --git a/lua/nvim-lsp-installer/installers/opam.lua b/lua/nvim-lsp-installer/installers/opam.lua
deleted file mode 100644
index 349810ce..00000000
--- a/lua/nvim-lsp-installer/installers/opam.lua
+++ /dev/null
@@ -1,60 +0,0 @@
-require "nvim-lsp-installer.notify"(
- (
- "%s has been deprecated. See https://github.com/williamboman/nvim-lsp-installer/wiki/Async-infrastructure-changes-notice"
- ):format "nvim-lsp-installer.installers.opam",
- vim.log.levels.WARN
-)
-
-local std = require "nvim-lsp-installer.installers.std"
-local installers = require "nvim-lsp-installer.installers"
-local process = require "nvim-lsp-installer.process"
-local path = require "nvim-lsp-installer.path"
-local Data = require "nvim-lsp-installer.data"
-
-local list_copy = Data.list_copy
-
-local M = {}
-
----@param packages string[] The OPAM packages to install. The first item in this list will be the recipient of the server version, should the user request a specific one.
-function M.packages(packages)
- return installers.pipe {
- std.ensure_executables {
- { "opam", "opam was not found in path, refer to https://opam.ocaml.org/doc/Install.html" },
- },
- ---@type ServerInstallerFunction
- function(_, callback, ctx)
- local pkgs = list_copy(packages)
-
- ctx.receipt:with_primary_source(ctx.receipt.opam(pkgs[1]))
- for i = 2, #pkgs do
- ctx.receipt:with_secondary_source(ctx.receipt.opam(pkgs[i]))
- end
-
- if ctx.requested_server_version then
- pkgs[1] = ("%s.%s"):format(pkgs[1], ctx.requested_server_version)
- end
-
- local install_args = {
- "install",
- ("--destdir=%s"):format(ctx.install_dir),
- "--yes",
- "--verbose",
- }
- vim.list_extend(install_args, pkgs)
-
- process.spawn("opam", {
- args = install_args,
- cwd = ctx.install_dir,
- stdio_sink = ctx.stdio_sink,
- }, callback)
- end,
- }
-end
-
-function M.env(root_dir)
- return {
- PATH = process.extend_path { path.concat { root_dir, "bin" } },
- }
-end
-
-return M
diff --git a/lua/nvim-lsp-installer/installers/pip3.lua b/lua/nvim-lsp-installer/installers/pip3.lua
deleted file mode 100644
index a7c8b13c..00000000
--- a/lua/nvim-lsp-installer/installers/pip3.lua
+++ /dev/null
@@ -1,91 +0,0 @@
-require "nvim-lsp-installer.notify"(
- (
- "%s has been deprecated. See https://github.com/williamboman/nvim-lsp-installer/wiki/Async-infrastructure-changes-notice"
- ):format "nvim-lsp-installer.installers.pip3",
- vim.log.levels.WARN
-)
-
-local path = require "nvim-lsp-installer.path"
-local Data = require "nvim-lsp-installer.data"
-local installers = require "nvim-lsp-installer.installers"
-local std = require "nvim-lsp-installer.installers.std"
-local platform = require "nvim-lsp-installer.platform"
-local process = require "nvim-lsp-installer.process"
-local settings = require "nvim-lsp-installer.settings"
-local context = require "nvim-lsp-installer.installers.context"
-local log = require "nvim-lsp-installer.log"
-
-local M = {}
-
-local REL_INSTALL_DIR = "venv"
-
----@param python_executable string
----@param packages string[]
-local function create_installer(python_executable, packages)
- return installers.pipe {
- std.ensure_executables {
- {
- python_executable,
- ("%s was not found in path. Refer to https://www.python.org/downloads/."):format(python_executable),
- },
- },
- ---@type ServerInstallerFunction
- function(_, callback, ctx)
- local pkgs = Data.list_copy(packages or {})
- local c = process.chain {
- cwd = ctx.install_dir,
- stdio_sink = ctx.stdio_sink,
- env = process.graft_env(M.env(ctx.install_dir)),
- }
-
- ctx.receipt:with_primary_source(ctx.receipt.pip3(pkgs[1]))
- for i = 2, #pkgs do
- ctx.receipt:with_secondary_source(ctx.receipt.pip3(pkgs[i]))
- end
-
- c.run(python_executable, { "-m", "venv", REL_INSTALL_DIR })
- if ctx.requested_server_version then
- -- The "head" package is the recipient for the requested version. It's.. by design... don't ask.
- pkgs[1] = ("%s==%s"):format(pkgs[1], ctx.requested_server_version)
- end
-
- local install_command = { "-m", "pip", "install", "-U" }
- vim.list_extend(install_command, settings.current.pip.install_args)
- c.run("python", vim.list_extend(install_command, pkgs))
-
- c.spawn(callback)
- end,
- }
-end
-
----@param packages string[] @The pip packages to install. The first item in this list will be the recipient of the server version, should the user request a specific one.
-function M.packages(packages)
- local py3 = create_installer("python3", packages)
- local py = create_installer("python", packages)
- -- see https://github.com/williamboman/nvim-lsp-installer/issues/128
- local installer_variants = platform.is_win and { py, py3 } or { py3, py }
-
- local py3_host_prog = vim.g.python3_host_prog
- if py3_host_prog then
- log.fmt_trace("Found python3_host_prog (%s)", py3_host_prog)
- table.insert(installer_variants, 1, create_installer(py3_host_prog, packages))
- end
-
- return installers.pipe {
- context.promote_install_dir(),
- installers.first_successful(installer_variants),
- }
-end
-
----@param root_dir string @The directory to resolve the executable from.
-function M.env(root_dir)
- return {
- PATH = process.extend_path { M.path(root_dir) },
- }
-end
-
-function M.path(root_dir)
- return path.concat { root_dir, REL_INSTALL_DIR, platform.is_win and "Scripts" or "bin" }
-end
-
-return M
diff --git a/lua/nvim-lsp-installer/installers/shell.lua b/lua/nvim-lsp-installer/installers/shell.lua
deleted file mode 100644
index 2cc8a845..00000000
--- a/lua/nvim-lsp-installer/installers/shell.lua
+++ /dev/null
@@ -1,117 +0,0 @@
-require "nvim-lsp-installer.notify"(
- (
- "%s has been deprecated. See https://github.com/williamboman/nvim-lsp-installer/wiki/Async-infrastructure-changes-notice"
- ):format "nvim-lsp-installer.installers.shell",
- vim.log.levels.WARN
-)
-
-local installers = require "nvim-lsp-installer.installers"
-local process = require "nvim-lsp-installer.process"
-
-local M = {}
-
----@param opts {shell: string, cmd: string[], env: table|nil}
-local function shell(opts)
- ---@type ServerInstallerFunction
- return function(_, callback, context)
- local _, stdio = process.spawn(opts.shell, {
- args = opts.args,
- cwd = context.install_dir,
- stdio_sink = context.stdio_sink,
- env = process.graft_env(opts.env or {}, {
- "PSMODULEPATH", -- https://github.com/williamboman/nvim-lsp-installer/issues/271
- }),
- }, callback)
-
- if stdio and opts.cmd then
- local stdin = stdio[1]
-
- stdin:write(opts.cmd)
- stdin:write "\n"
- stdin:close()
- end
- end
-end
-
----@param raw_script string @The bash script to execute as-is.
----@param opts {prefix: string, env: table}
-function M.bash(raw_script, opts)
- local default_opts = {
- prefix = "set -euo pipefail;",
- env = {},
- }
- opts = vim.tbl_deep_extend("force", default_opts, opts or {})
-
- return shell {
- shell = "bash",
- args = { "-c", (opts.prefix or "") .. raw_script },
- env = opts.env,
- }
-end
-
----@param raw_script string @The sh script to execute as-is.
----@param opts {prefix: string, env: table}
-function M.sh(raw_script, opts)
- local default_opts = {
- prefix = "set -eu;",
- env = {},
- }
- opts = vim.tbl_deep_extend("force", default_opts, opts or {})
-
- return shell {
- shell = "sh",
- cmd = (opts.prefix or "") .. raw_script,
- env = opts.env,
- }
-end
-
----@param raw_script string @The cmd.exe script to execute as-is.
----@param opts {env: table}
-function M.cmd(raw_script, opts)
- local default_opts = {
- env = {},
- }
- opts = vim.tbl_deep_extend("force", default_opts, opts or {})
-
- return shell {
- shell = "cmd.exe",
- args = { "/C", raw_script },
- env = opts.env,
- }
-end
-
----@param raw_script string @The powershell script to execute as-is.
----@param opts {prefix: string, env: table}
-function M.powershell(raw_script, opts)
- local default_opts = {
- env = {},
- -- YIKES https://stackoverflow.com/a/63301751
- prefix = [[
- $ProgressPreference = 'SilentlyContinue';
- [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
- ]],
- }
- opts = vim.tbl_deep_extend("force", default_opts, opts or {})
-
- return shell {
- shell = "powershell.exe",
- args = { "-NoProfile", "-Command", (opts.prefix or "") .. raw_script },
- env = opts.env,
- }
-end
-
----@param raw_script string @A script that is compatible with bash and cmd.exe.
----@param opts {env: table}
-function M.polyshell(raw_script, opts)
- local default_opts = {
- env = {},
- }
- opts = vim.tbl_deep_extend("force", default_opts, opts or {})
-
- return installers.when {
- unix = M.bash(raw_script, { env = opts.env }),
- win = M.cmd(raw_script, { env = opts.env }),
- }
-end
-
-return M
diff --git a/lua/nvim-lsp-installer/installers/std.lua b/lua/nvim-lsp-installer/installers/std.lua
deleted file mode 100644
index 9db1251c..00000000
--- a/lua/nvim-lsp-installer/installers/std.lua
+++ /dev/null
@@ -1,344 +0,0 @@
-require "nvim-lsp-installer.notify"(
- (
- "%s has been deprecated. See https://github.com/williamboman/nvim-lsp-installer/wiki/Async-infrastructure-changes-notice"
- ):format "nvim-lsp-installer.installers.std",
- vim.log.levels.WARN
-)
-
-local path = require "nvim-lsp-installer.path"
-local fs = require "nvim-lsp-installer.fs"
-local process = require "nvim-lsp-installer.process"
-local platform = require "nvim-lsp-installer.platform"
-local installers = require "nvim-lsp-installer.installers"
-local shell = require "nvim-lsp-installer.installers.shell"
-local Data = require "nvim-lsp-installer.data"
-
-local list_not_nil, when = Data.list_not_nil, Data.when
-
-local USER_AGENT = "nvim-lsp-installer (+https://github.com/williamboman/nvim-lsp-installer)"
-
-local M = {}
-
----@param url string @The url to download.
----@param out_file string @The relative path to where to write the contents of the url.
-function M.download_file(url, out_file)
- return installers.when {
- ---@type ServerInstallerFunction
- unix = function(_, callback, context)
- context.stdio_sink.stdout(("Downloading file %q...\n"):format(url))
- process.attempt {
- jobs = {
- process.lazy_spawn("wget", {
- args = { "--header", ("User-Agent: %s"):format(USER_AGENT), "-nv", "-O", out_file, url },
- cwd = context.install_dir,
- stdio_sink = context.stdio_sink,
- }),
- process.lazy_spawn("curl", {
- args = { "-H", ("User-Agent: %s"):format(USER_AGENT), "-fsSL", "-o", out_file, url },
- cwd = context.install_dir,
- stdio_sink = context.stdio_sink,
- }),
- },
- on_finish = callback,
- }
- end,
- win = shell.powershell(
- ("iwr -Headers @{'User-Agent' = '%s'} -UseBasicParsing -Uri %q -OutFile %q"):format(
- USER_AGENT,
- url,
- out_file
- )
- ),
- }
-end
-
----@param file string @The relative path to the file to unzip.
----@param dest string|nil @The destination of the unzip.
-function M.unzip(file, dest)
- return installers.pipe {
- installers.when {
- ---@type ServerInstallerFunction
- unix = function(_, callback, context)
- process.spawn("unzip", {
- args = { "-d", dest, file },
- cwd = context.install_dir,
- stdio_sink = context.stdio_sink,
- }, callback)
- end,
- win = shell.powershell(
- ("Microsoft.PowerShell.Archive\\Expand-Archive -Path %q -DestinationPath %q"):format(file, dest)
- ),
- },
- installers.always_succeed(M.rmrf(file)),
- }
-end
-
----@see unzip().
----@param url string @The url of the .zip file.
----@param dest string|nil @The url of the .zip file. Defaults to ".".
-function M.unzip_remote(url, dest)
- return installers.pipe {
- M.download_file(url, "archive.zip"),
- M.unzip("archive.zip", dest or "."),
- }
-end
-
----@param file string @The relative path to the tar file to extract.
-function M.untar(file)
- return installers.pipe {
- ---@type ServerInstallerFunction
- function(_, callback, context)
- process.spawn("tar", {
- args = { "-xvf", file },
- cwd = context.install_dir,
- stdio_sink = context.stdio_sink,
- }, callback)
- end,
- installers.always_succeed(M.rmrf(file)),
- }
-end
-
----@param file string
-local function win_extract(file)
- return installers.pipe {
- ---@type ServerInstallerFunction
- function(_, callback, context)
- -- The trademarked "throw shit until it sticks" technique
- local sevenzip = process.lazy_spawn("7z", {
- args = { "x", "-y", "-r", file },
- cwd = context.install_dir,
- stdio_sink = context.stdio_sink,
- })
- local peazip = process.lazy_spawn("peazip", {
- args = { "-ext2here", path.concat { context.install_dir, file } }, -- peazip require absolute paths, or else!
- cwd = context.install_dir,
- stdio_sink = context.stdio_sink,
- })
- local winzip = process.lazy_spawn("wzunzip", {
- args = { file },
- cwd = context.install_dir,
- stdio_sink = context.stdio_sink,
- })
- local winrar = process.lazy_spawn("winrar", {
- args = { "e", file },
- cwd = context.install_dir,
- stdio_sink = context.stdio_sink,
- })
- process.attempt {
- jobs = { sevenzip, peazip, winzip, winrar },
- on_finish = callback,
- }
- end,
- installers.always_succeed(M.rmrf(file)),
- }
-end
-
----@param file string
-local function win_untarxz(file)
- return installers.pipe {
- win_extract(file),
- M.untar(file:gsub(".xz$", "")),
- }
-end
-
----@param file string
-local function win_arc_unarchive(file)
- return installers.pipe {
- ---@type ServerInstallerFunction
- function(_, callback, context)
- context.stdio_sink.stdout "Attempting to unarchive using arc."
- process.spawn("arc", {
- args = { "unarchive", file },
- cwd = context.install_dir,
- stdio_sink = context.stdio_sink,
- }, callback)
- end,
- installers.always_succeed(M.rmrf(file)),
- }
-end
-
----@param url string @The url to the .tar.xz file to extract.
-function M.untarxz_remote(url)
- return installers.pipe {
- M.download_file(url, "archive.tar.xz"),
- installers.when {
- unix = M.untar "archive.tar.xz",
- win = installers.first_successful {
- win_untarxz "archive.tar.xz",
- win_arc_unarchive "archive.tar.xz",
- },
- },
- }
-end
-
----@param url string @The url to the .tar.gz file to extract.
-function M.untargz_remote(url)
- return installers.pipe {
- M.download_file(url, "archive.tar.gz"),
- M.untar "archive.tar.gz",
- }
-end
-
----@param file string @The relative path to the file to gunzip.
-function M.gunzip(file)
- return installers.when {
- ---@type ServerInstallerFunction
- unix = function(_, callback, context)
- process.spawn("gzip", {
- args = { "-d", file },
- cwd = context.install_dir,
- stdio_sink = context.stdio_sink,
- }, callback)
- end,
- win = win_extract(file),
- }
-end
-
----@see gunzip()
----@param url string @The url to the .gz file to extract.
----@param out_file string|nil @The name of the extracted .gz file.
-function M.gunzip_remote(url, out_file)
- local archive = ("%s.gz"):format(out_file or "archive")
- return installers.pipe {
- M.download_file(url, archive),
- M.gunzip(archive),
- installers.always_succeed(M.rmrf(archive)),
- }
-end
-
----Recursively deletes the provided path. Will fail on paths that are not inside the configured install_root_dir.
----@param rel_path string @The relative path to the file/directory to remove.
-function M.rmrf(rel_path)
- ---@type ServerInstallerFunction
- return function(_, callback, context)
- local abs_path = path.concat { context.install_dir, rel_path }
- context.stdio_sink.stdout(("Deleting %q\n"):format(abs_path))
- vim.schedule(function()
- local ok = pcall(fs.rmrf, abs_path)
- if ok then
- callback(true)
- else
- context.stdio_sink.stderr(("Failed to delete %q.\n"):format(abs_path))
- callback(false)
- end
- end)
- end
-end
-
----@param rel_path string @The relative path to the file to write.
----@param contents string @The file contents.
-function M.write_file(rel_path, contents)
- ---@type ServerInstallerFunction
- return function(_, callback, ctx)
- local file = path.concat { ctx.install_dir, rel_path }
- ctx.stdio_sink.stdout(("Writing file %q\n"):format(file))
- fs.write_file(file, contents)
- callback(true)
- end
-end
-
----Shallow git clone.
----@param repo_url string
----@param opts {directory: string, recursive: boolean}
-function M.git_clone(repo_url, opts)
- ---@type ServerInstallerFunction
- return function(_, callback, context)
- opts = vim.tbl_deep_extend("force", {
- directory = ".",
- recursive = false,
- }, opts or {})
-
- local c = process.chain {
- cwd = context.install_dir,
- stdio_sink = context.stdio_sink,
- }
-
- c.run(
- "git",
- list_not_nil(
- "clone",
- "--depth",
- "1",
- when(opts.recursive, "--recursive"),
- when(opts.recursive, "--shallow-submodules"),
- repo_url,
- opts.directory
- )
- )
-
- if context.requested_server_version then
- c.run("git", { "-C", opts.directory, "fetch", "--depth", "1", "origin", context.requested_server_version })
- c.run("git", { "-C", opts.directory, "checkout", "FETCH_HEAD" })
- end
-
- c.spawn(callback)
- end
-end
-
----@param opts {args: string[]}
-function M.gradlew(opts)
- ---@type ServerInstallerFunction
- return function(_, callback, context)
- process.spawn(path.concat { context.install_dir, platform.is_win and "gradlew.bat" or "gradlew" }, {
- args = opts.args,
- cwd = context.install_dir,
- stdio_sink = context.stdio_sink,
- }, callback)
- end
-end
-
----Creates an installer that ensures that the provided executables are available in the current runtime.
----@param executables string[][] @A list of (executable, error_msg) tuples.
----@return ServerInstallerFunction
-function M.ensure_executables(executables)
- return vim.schedule_wrap(
- ---@type ServerInstallerFunction
- function(_, callback, context)
- local has_error = false
- for i = 1, #executables do
- local entry = executables[i]
- local executable = entry[1]
- local error_msg = entry[2]
- if vim.fn.executable(executable) ~= 1 then
- has_error = true
- context.stdio_sink.stderr(error_msg .. "\n")
- end
- end
- callback(not has_error)
- end
- )
-end
-
----@path old_path string @The relative path to the file/dir to rename.
----@path new_path string @The relative path to what to rename the file/dir to.
-function M.rename(old_path, new_path)
- ---@type ServerInstallerFunction
- return function(_, callback, context)
- local ok = pcall(
- fs.rename,
- path.concat { context.install_dir, old_path },
- path.concat { context.install_dir, new_path }
- )
- if not ok then
- context.stdio_sink.stderr(("Failed to rename %q to %q.\n"):format(old_path, new_path))
- end
- callback(ok)
- end
-end
-
----@param flags string @The chmod flag to apply.
----@param files string[] @A list of relative paths to apply the chmod on.
-function M.chmod(flags, files)
- return installers.on {
- ---@type ServerInstallerFunction
- unix = function(_, callback, context)
- process.spawn("chmod", {
- args = vim.list_extend({ flags }, files),
- cwd = context.install_dir,
- stdio_sink = context.stdio_sink,
- }, callback)
- end,
- }
-end
-
-return M