aboutsummaryrefslogtreecommitdiffstats
path: root/lua/mason-core/platform.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/mason-core/platform.lua')
-rw-r--r--lua/mason-core/platform.lua110
1 files changed, 73 insertions, 37 deletions
diff --git a/lua/mason-core/platform.lua b/lua/mason-core/platform.lua
index 15ebdd47..f1a25666 100644
--- a/lua/mason-core/platform.lua
+++ b/lua/mason-core/platform.lua
@@ -1,4 +1,4 @@
-local fun = require "mason-core.functional.function"
+local _ = require "mason-core.functional"
local M = {}
@@ -21,28 +21,83 @@ local arch_aliases = {
}
M.arch = arch_aliases[uname.machine] or uname.machine
+M.sysname = uname.sysname
-M.is_win = vim.fn.has "win32" == 1
-M.is_unix = vim.fn.has "unix" == 1
-M.is_mac = vim.fn.has "mac" == 1
-M.is_linux = not M.is_mac and M.is_unix
+M.is_headless = #vim.api.nvim_list_uis() == 0
--- PATH separator
-M.path_sep = M.is_win and ";" or ":"
+-- @return string @The libc found on the system, musl or glibc (glibc if ldd is not found)
+local get_libc = _.lazy(function()
+ local _, _, libc_exit_code = os.execute "ldd --version 2>&1 | grep -q musl"
+ if libc_exit_code == 0 then
+ return "musl"
+ else
+ return "glibc"
+ end
+end)
-M.is_headless = #vim.api.nvim_list_uis() == 0
+-- Most of the code that calls into these functions executes outside of the main event loop, where API/fn functions are
+-- disabled. We evaluate these immediately here to avoid issues with main loop synchronization.
+local cached_features = {
+ ["win"] = vim.fn.has "win32",
+ ["win32"] = vim.fn.has "win32",
+ ["win64"] = vim.fn.has "win64",
+ ["mac"] = vim.fn.has "mac",
+ ["unix"] = vim.fn.has "unix",
+ ["linux"] = vim.fn.has "linux",
+}
+
+---@type fun(env: string): boolean
+local check_env = _.memoize(_.cond {
+ {
+ _.equals "musl",
+ function()
+ return get_libc() == "musl"
+ end,
+ },
+ {
+ _.equals "gnu",
+ function()
+ return get_libc() == "glibc"
+ end,
+ },
+ { _.equals "openbsd", _.always(uname.sysname == "OpenBSD") },
+ { _.T, _.F },
+})
+
+---Table that allows for checking whether the provided targets apply to the current system.
+---Each key is a target tuple consisting of at most 3 targets, in the following order:
+--- 1) OS (e.g. linux, unix, mac, win) - Mandatory
+--- 2) Architecture (e.g. arm64, x64) - Optional
+--- 3) Environment (e.g. gnu, musl, openbsd) - Optional
+---Each target is separated by a "_" character, like so: "linux_x64_musl".
+---@type table<string, boolean>
+M.is = setmetatable({}, {
+ __index = function(__, key)
+ local os, arch, env = unpack(vim.split(key, "_", { plain = true }))
+ if not cached_features[os] or cached_features[os] ~= 1 then
+ return false
+ end
+ if arch and arch ~= M.arch then
+ return false
+ end
+ if env and not check_env(env) then
+ return false
+ end
+ return true
+ end,
+})
---@generic T
---@param platform_table table<Platform, T>
---@return T
local function get_by_platform(platform_table)
- if M.is_mac then
+ if M.is.mac then
return platform_table.mac or platform_table.unix
- elseif M.is_linux then
+ elseif M.is.linux then
return platform_table.linux or platform_table.unix
- elseif M.is_unix then
+ elseif M.is.unix then
return platform_table.unix
- elseif M.is_win then
+ elseif M.is.win then
return platform_table.win
else
return nil
@@ -59,7 +114,7 @@ function M.when(cases)
end
---@type async fun(): table
-M.os_distribution = fun.lazy(function()
+M.os_distribution = _.lazy(function()
local Result = require "mason-core.result"
---Parses the provided contents of an /etc/\*-release file and identifies the Linux distribution.
@@ -122,8 +177,8 @@ M.os_distribution = fun.lazy(function()
end)
---@type async fun(): Result<string>
-M.get_homebrew_prefix = fun.lazy(function()
- assert(M.is_mac, "Can only locate Homebrew installation on Mac systems.")
+M.get_homebrew_prefix = _.lazy(function()
+ assert(M.is.mac, "Can only locate Homebrew installation on Mac systems.")
local spawn = require "mason-core.spawn"
return spawn
.brew({ "--prefix" })
@@ -135,31 +190,9 @@ M.get_homebrew_prefix = fun.lazy(function()
end)
end)
--- @return string @The libc found on the system, musl or glibc (glibc if ldd is not found)
-M.get_libc = fun.lazy(function()
- local _, _, libc_exit_code = os.execute "ldd --version 2>&1 | grep -q musl"
- if libc_exit_code == 0 then
- return "musl"
- else
- return "glibc"
- end
-end)
-
----@type table<string, boolean>
-M.is = setmetatable({}, {
- __index = function(_, key)
- local platform, arch = unpack(vim.split(key, "_", { plain = true }))
- if arch and M.arch ~= arch then
- return false
- end
- return M["is_" .. platform] == true
- end,
-})
-
---@async
function M.get_node_version()
local spawn = require "mason-core.spawn"
- local _ = require "mason-core.functional"
return spawn.node({ "--version" }):map(function(result)
-- Parses output such as "v16.3.1" into major, minor, patch
@@ -168,4 +201,7 @@ function M.get_node_version()
end)
end
+-- PATH separator
+M.path_sep = M.is.win and ";" or ":"
+
return M