aboutsummaryrefslogtreecommitdiffstats
path: root/lua/mason-core/installer/init.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/mason-core/installer/init.lua')
-rw-r--r--lua/mason-core/installer/init.lua123
1 files changed, 78 insertions, 45 deletions
diff --git a/lua/mason-core/installer/init.lua b/lua/mason-core/installer/init.lua
index a11de45d..8e05cb20 100644
--- a/lua/mason-core/installer/init.lua
+++ b/lua/mason-core/installer/init.lua
@@ -17,24 +17,34 @@ local M = {}
---@async
local function create_prefix_dirs()
- for _, p in ipairs { path.install_prefix(), path.bin_prefix(), path.package_prefix(), path.package_build_prefix() } do
- if not fs.async.dir_exists(p) then
- fs.async.mkdirp(p)
+ return Result.try(function(try)
+ for _, p in ipairs {
+ path.install_prefix(),
+ path.bin_prefix(),
+ path.share_prefix(),
+ path.package_prefix(),
+ path.package_build_prefix(),
+ } do
+ if not fs.async.dir_exists(p) then
+ try(Result.pcall(fs.async.mkdirp, p))
+ end
end
- end
+ end)
end
---@async
---@param context InstallContext
local function write_receipt(context)
- log.fmt_debug("Writing receipt for %s", context.package)
- context.receipt
- :with_name(context.package.name)
- :with_schema_version("1.0")
- :with_completion_time(vim.loop.gettimeofday())
- local receipt_path = path.concat { context.cwd:get(), "mason-receipt.json" }
- local install_receipt = context.receipt:build()
- fs.async.write_file(receipt_path, vim.json.encode(install_receipt))
+ return Result.pcall(function()
+ log.fmt_debug("Writing receipt for %s", context.package)
+ context.receipt
+ :with_name(context.package.name)
+ :with_schema_version("1.1")
+ :with_completion_time(vim.loop.gettimeofday())
+ local receipt_path = path.concat { context.cwd:get(), "mason-receipt.json" }
+ local install_receipt = context.receipt:build()
+ fs.async.write_file(receipt_path, vim.json.encode(install_receipt))
+ end)
end
local CONTEXT_REQUEST = {}
@@ -47,13 +57,17 @@ end
---@async
---@param context InstallContext
function M.prepare_installer(context)
- create_prefix_dirs()
- local package_build_prefix = path.package_build_prefix(context.package.name)
- if fs.async.dir_exists(package_build_prefix) then
- fs.async.rmrf(package_build_prefix)
- end
- fs.async.mkdirp(package_build_prefix)
- context.cwd:set(package_build_prefix)
+ return Result.try(function(try)
+ try(create_prefix_dirs())
+ local package_build_prefix = path.package_build_prefix(context.package.name)
+ if fs.async.dir_exists(package_build_prefix) then
+ try(Result.pcall(fs.async.rmrf, package_build_prefix))
+ end
+ try(Result.pcall(fs.async.mkdirp, package_build_prefix))
+ context.cwd:set(package_build_prefix)
+
+ return context.package.spec.install
+ end)
end
---@async
@@ -81,12 +95,40 @@ function M.exec_in_context(context, fn)
end
end
context.receipt:with_start_time(vim.loop.gettimeofday())
- M.prepare_installer(context)
step(context)
return ret_val
end
---@async
+---@param context InstallContext
+---@param installer async fun(ctx: InstallContext)
+local function run_installer(context, installer)
+ local handle = context.handle
+ return Result.pcall(function()
+ return a.wait(function(resolve, reject)
+ local cancel_thread = a.run(M.exec_in_context, function(success, result)
+ if success then
+ resolve(result)
+ else
+ reject(result)
+ end
+ end, context, installer)
+
+ handle:once("terminate", function()
+ cancel_thread()
+ if handle:is_closed() then
+ reject "Installation was aborted."
+ else
+ handle:once("closed", function()
+ reject "Installation was aborted."
+ end)
+ end
+ end)
+ end)
+ end)
+end
+
+---@async
---@param handle InstallHandle
---@param opts PackageInstallOpts
function M.execute(handle, opts)
@@ -117,34 +159,25 @@ function M.execute(handle, opts)
handle:on("stderr", append_log)
end
- log.fmt_info("Executing installer for %s", pkg)
- return Result.run_catching(function()
- -- 1. run installer
- a.wait(function(resolve, reject)
- local cancel_thread = a.run(M.exec_in_context, function(success, result)
- if success then
- resolve(result)
- else
- reject(result)
- end
- end, context, pkg.spec.install)
+ log.fmt_info("Executing installer for %s version=%s", pkg, opts.version or "latest")
- handle:once("terminate", function()
- handle:once("closed", function()
- reject "Installation was aborted."
- end)
- cancel_thread()
- end)
- end)
+ return Result.try(function(try)
+ -- 1. prepare directories and initialize cwd
+ local installer = try(M.prepare_installer(context))
+
+ -- 2. execute installer
+ try(run_installer(context, installer))
- -- 2. promote temporary installation dir
- context:promote_cwd()
+ -- 3. promote temporary installation dir
+ try(Result.pcall(function()
+ context:promote_cwd()
+ end))
- -- 3. link package
- linker.link(context)
+ -- 4. link package
+ try(linker.link(context))
- -- 4. write receipt
- write_receipt(context)
+ -- 5. write receipt
+ try(write_receipt(context))
end)
:on_success(function()
permit:forget()
@@ -173,7 +206,7 @@ function M.execute(handle, opts)
end
-- unlink linked executables (in the rare occasion an error occurs after linking)
- linker.unlink(context.package, context.receipt.links)
+ linker.unlink(context.package, context.receipt)
if not handle:is_closed() and not handle.is_terminated then
handle:close()