summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2025-03-03 18:19:20 +0100
committerWilliam Boman <william@redwill.se>2025-03-03 18:19:20 +0100
commit7e0d8c442ab6e1ec69682d8d1bdaadc4d43a53ee (patch)
tree519664ddab57ccc264a298b42403cab0e32d708c
parentv2.0.0-rc.2 (diff)
downloadmason-7e0d8c442ab6e1ec69682d8d1bdaadc4d43a53ee.tar
mason-7e0d8c442ab6e1ec69682d8d1bdaadc4d43a53ee.tar.gz
mason-7e0d8c442ab6e1ec69682d8d1bdaadc4d43a53ee.tar.bz2
mason-7e0d8c442ab6e1ec69682d8d1bdaadc4d43a53ee.tar.lz
mason-7e0d8c442ab6e1ec69682d8d1bdaadc4d43a53ee.tar.xz
mason-7e0d8c442ab6e1ec69682d8d1bdaadc4d43a53ee.tar.zst
mason-7e0d8c442ab6e1ec69682d8d1bdaadc4d43a53ee.zip
refactor(command): use callback in Package:install() when running :MasonInstall in headless mode
-rw-r--r--lua/mason-core/installer/InstallRunner.lua2
-rw-r--r--lua/mason/api/command.lua97
-rw-r--r--tests/mason/api/command_spec.lua14
3 files changed, 56 insertions, 57 deletions
diff --git a/lua/mason-core/installer/InstallRunner.lua b/lua/mason-core/installer/InstallRunner.lua
index cfa9ed37..da9e775d 100644
--- a/lua/mason-core/installer/InstallRunner.lua
+++ b/lua/mason-core/installer/InstallRunner.lua
@@ -31,7 +31,7 @@ function InstallRunner:new(handle, semaphore)
return instance
end
----@alias InstallRunnerCallback fun(success: true, receipt: InstallReceipt) | fun(success: false, handle: InstallHandle, error: any)
+---@alias InstallRunnerCallback fun(success: true, receipt: InstallReceipt) | fun(success: false, error: any)
---@param opts PackageInstallOpts
---@param callback? InstallRunnerCallback
diff --git a/lua/mason/api/command.lua b/lua/mason/api/command.lua
index ea466351..4b1c3bef 100644
--- a/lua/mason/api/command.lua
+++ b/lua/mason/api/command.lua
@@ -25,61 +25,11 @@ local get_valid_packages = _.filter_map(function(pkg_specifier)
end
end)
----@param handles InstallHandle[]
-local function join_handles(handles)
- local a = require "mason-core.async"
- local Optional = require "mason-core.optional"
-
- _.each(
- ---@param handle InstallHandle
- function(handle)
- handle:on("stdout", vim.schedule_wrap(vim.api.nvim_out_write))
- handle:on("stderr", vim.schedule_wrap(vim.api.nvim_err_write))
- end,
- handles
- )
-
- a.run_blocking(function()
- a.wait_all(_.map(
- ---@param handle InstallHandle
- function(handle)
- return function()
- a.wait(function(resolve)
- if handle:is_closed() then
- resolve()
- else
- handle:once("closed", resolve)
- end
- end)
- end
- end,
- handles
- ))
- local failed_packages = _.filter_map(function(handle)
- -- TODO: Use new install callback to determine success.
- if not handle.package:is_installed() then
- return Optional.of(handle.package.name)
- else
- return Optional.empty()
- end
- end, handles)
-
- if _.length(failed_packages) > 0 then
- a.wait(vim.schedule) -- wait for scheduler for logs to finalize
- a.wait(vim.schedule) -- logs have been written
- vim.api.nvim_err_writeln ""
- vim.api.nvim_err_writeln(
- ("The following packages failed to install: %s"):format(_.join(", ", failed_packages))
- )
- vim.cmd [[1cq]]
- end
- end)
-end
-
---@param package_specifiers string[]
---@param opts? table<string, string | boolean>
local function MasonInstall(package_specifiers, opts)
opts = opts or {}
+ local a = require "mason-core.async"
local registry = require "mason-registry"
local Optional = require "mason-core.optional"
@@ -105,7 +55,50 @@ local function MasonInstall(package_specifiers, opts)
-- This is to avoid things like scripts silently not erroring even if they've provided one or more invalid packages.
return vim.cmd [[1cq]]
end
- join_handles(install_packages(valid_packages))
+ a.run_blocking(function()
+ local results = {
+ a.wait_all(_.map(
+ ---@param target { pkg: Package, version: string? }
+ function(target)
+ return function()
+ if target.pkg:is_installing() then
+ return
+ end
+ return a.wait(function(resolve)
+ local handle = target.pkg:install({
+ version = target.version,
+ debug = opts.debug,
+ force = opts.force,
+ strict = opts.strict,
+ target = opts.target,
+ }, function(success, err)
+ resolve { success, target.pkg, err }
+ end)
+ if not opts.quiet then
+ handle
+ :on("stdout", vim.schedule_wrap(vim.api.nvim_out_write))
+ :on("stderr", vim.schedule_wrap(vim.api.nvim_err_write))
+ end
+ end)
+ end
+ end,
+ valid_packages
+ )),
+ }
+ a.scheduler()
+
+ local is_failure = _.compose(_.equals(false), _.head)
+ if _.any(is_failure, results) then
+ local failures = _.filter(is_failure, results)
+ local failed_packages = _.map(_.nth(2), failures)
+ for _, failure in ipairs(failures) do
+ local _, pkg, error = unpack(failure)
+ vim.api.nvim_err_writeln(("Package %s failed with the following error:"):format(pkg.name))
+ vim.api.nvim_err_writeln(tostring(error))
+ end
+ vim.cmd [[1cq]]
+ end
+ end)
else
local ui = require "mason.ui"
ui.open()
diff --git a/tests/mason/api/command_spec.lua b/tests/mason/api/command_spec.lua
index 6945340d..673e530b 100644
--- a/tests/mason/api/command_spec.lua
+++ b/tests/mason/api/command_spec.lua
@@ -25,8 +25,10 @@ describe(":MasonInstall", function()
spy.on(Pkg, "install")
api.MasonInstall { "dummy@1.0.0", "dummy2" }
assert.spy(Pkg.install).was_called(2)
- assert.spy(Pkg.install).was_called_with(match.is_ref(dummy), { version = "1.0.0" })
- assert.spy(Pkg.install).was_called_with(match.is_ref(dummy2), match.tbl_containing { version = match.is_nil() })
+ assert.spy(Pkg.install).was_called_with(match.is_ref(dummy), { version = "1.0.0" }, match.is_function())
+ assert
+ .spy(Pkg.install)
+ .was_called_with(match.is_ref(dummy2), match.tbl_containing { version = match.is_nil() }, match.is_function())
end)
it("should install provided packages in debug mode", function()
@@ -35,8 +37,12 @@ describe(":MasonInstall", function()
spy.on(Pkg, "install")
vim.cmd [[MasonInstall --debug dummy dummy2]]
assert.spy(Pkg.install).was_called(2)
- assert.spy(Pkg.install).was_called_with(match.is_ref(dummy), { version = nil, debug = true })
- assert.spy(Pkg.install).was_called_with(match.is_ref(dummy2), { version = nil, debug = true })
+ assert
+ .spy(Pkg.install)
+ .was_called_with(match.is_ref(dummy), { version = nil, debug = true }, match.is_function())
+ assert
+ .spy(Pkg.install)
+ .was_called_with(match.is_ref(dummy2), { version = nil, debug = true }, match.is_function())
end)
it("should open the UI window", function()