From 999476c324b26223aaf409a84497215e18d74499 Mon Sep 17 00:00:00 2001 From: William Boman Date: Wed, 6 Apr 2022 00:25:50 +0200 Subject: switch majority of installers to async implementation (#574) --- lua/nvim-lsp-installer/server.lua | 100 ++++++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 37 deletions(-) (limited to 'lua/nvim-lsp-installer/server.lua') diff --git a/lua/nvim-lsp-installer/server.lua b/lua/nvim-lsp-installer/server.lua index 5597bba7..de6481a4 100644 --- a/lua/nvim-lsp-installer/server.lua +++ b/lua/nvim-lsp-installer/server.lua @@ -1,14 +1,17 @@ local dispatcher = require "nvim-lsp-installer.dispatcher" local a = require "nvim-lsp-installer.core.async" +local InstallContext = require "nvim-lsp-installer.core.installer.context" local fs = require "nvim-lsp-installer.fs" local log = require "nvim-lsp-installer.log" local platform = require "nvim-lsp-installer.platform" local settings = require "nvim-lsp-installer.settings" local installers = require "nvim-lsp-installer.installers" +local installer = require "nvim-lsp-installer.core.installer" local servers = require "nvim-lsp-installer.servers" local status_win = require "nvim-lsp-installer.ui.status-win" local path = require "nvim-lsp-installer.path" local receipt = require "nvim-lsp-installer.core.receipt" +local Optional = require "nvim-lsp-installer.core.optional" local M = {} @@ -25,6 +28,7 @@ M.get_server_root_path = servers.get_server_install_path ---@field public deprecated ServerDeprecation|nil @The existence (not nil) of this field indicates this server is depracted. ---@field public languages string[] ---@field private _installer ServerInstallerFunction +---@field private _async boolean ---@field private _on_ready_handlers fun(server: Server)[] ---@field private _default_options table @The server's default options. This is used in @see Server#setup. M.Server = {} @@ -38,9 +42,10 @@ function M.Server:new(opts) root_dir = opts.root_dir, homepage = opts.homepage, deprecated = opts.deprecated, + _async = opts.async or false, languages = opts.languages or {}, _on_ready_handlers = {}, - _installer = type(opts.installer) == "function" and opts.installer or installers.pipe(opts.installer), + _installer = opts.installer, _default_options = opts.default_options, }, M.Server) end @@ -208,47 +213,68 @@ end ---@param context ServerInstallContext ---@param callback ServerInstallCallback function M.Server:install_attached(context, callback) - a.run( - function() - context.receipt = receipt.InstallReceiptBuilder.new() - context.receipt:with_start_time(vim.loop.gettimeofday()) - + if self._async then + a.run(function() + local install_context = InstallContext.new { + name = self.name, + boundary_path = settings.current.install_root_dir, + stdio_sink = context.stdio_sink, + destination_dir = self.root_dir, + requested_version = Optional.of_nilable(context.requested_server_version), + } + installer.execute(install_context, self._installer):get_or_throw() a.scheduler() - self:_setup_install_context(context) - local async_installer = a.promisify(function(server, context, callback) - -- args are shifted - return self._installer(server, callback, context) - end) - assert(async_installer(self, context), "Installation failed.") - - a.scheduler() - if not self:promote_install_dir(context.install_dir) then - error(("Failed to promote the temporary installation directory %q."):format(context.install_dir)) + dispatcher.dispatch_server_ready(self) + for _, on_ready_handler in ipairs(self._on_ready_handlers) do + on_ready_handler(self) end + end, callback) + else + --- Deprecated + a.run( + function() + context.receipt = receipt.InstallReceiptBuilder.new() + context.receipt:with_start_time(vim.loop.gettimeofday()) + + a.scheduler() + self:_setup_install_context(context) + local async_installer = a.promisify(function(server, context, callback) + local normalized_installer = type(self._installer) == "function" and self._installer + or installers.pipe(self._installer) + -- args are shifted + return normalized_installer(server, callback, context) + end) + assert(async_installer(self, context), "Installation failed.") + + a.scheduler() + if not self:promote_install_dir(context.install_dir) then + error(("Failed to promote the temporary installation directory %q."):format(context.install_dir)) + end - self:_write_receipt(context.receipt) - - -- Dispatch the server is ready - vim.schedule(function() - dispatcher.dispatch_server_ready(self) - for _, on_ready_handler in ipairs(self._on_ready_handlers) do - on_ready_handler(self) + self:_write_receipt(context.receipt) + + -- Dispatch the server is ready + vim.schedule(function() + dispatcher.dispatch_server_ready(self) + for _, on_ready_handler in ipairs(self._on_ready_handlers) do + on_ready_handler(self) + end + end) + end, + vim.schedule_wrap(function(ok, result) + if not ok then + pcall(fs.rmrf, context.install_dir) + log.fmt_error("Server installation failed, server_name=%s, error=%s", self.name, result) + context.stdio_sink.stderr(tostring(result) .. "\n") end + -- The tmp dir should in most cases have been "promoted" and already renamed to its final destination, + -- but we make sure to delete it should the installer modify the installation working directory during + -- installation. + pcall(fs.rmrf, self:get_tmp_install_dir()) + callback(ok) end) - end, - vim.schedule_wrap(function(ok, result) - if not ok then - pcall(fs.rmrf, context.install_dir) - log.fmt_error("Server installation failed, server_name=%s, error=%s", self.name, result) - context.stdio_sink.stderr(tostring(result) .. "\n") - end - -- The tmp dir should in most cases have been "promoted" and already renamed to its final destination, - -- but we make sure to delete it should the installer modify the installation working directory during - -- installation. - pcall(fs.rmrf, self:get_tmp_install_dir()) - callback(ok) - end) - ) + ) + end end function M.Server:uninstall() -- cgit v1.2.3-70-g09d2