From a83eabdc8c49c0c93bf5bb162fa3b57404a9d095 Mon Sep 17 00:00:00 2001 From: William Boman Date: Tue, 30 Sep 2025 20:02:22 +0200 Subject: fix(spawn): always expand executable path on Windows (#2021) This fixes some issues with the logic for expanding paths on Windows. If a process is spawned with a custom `PATH` (either via the `env` or `env_raw` arg) we still expand the path manually but with a temporarily modified `vim.env.PATH`. Fixes #2009. --- lua/mason-core/spawn.lua | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) (limited to 'lua/mason-core') diff --git a/lua/mason-core/spawn.lua b/lua/mason-core/spawn.lua index d604dfe2..0da67569 100644 --- a/lua/mason-core/spawn.lua +++ b/lua/mason-core/spawn.lua @@ -14,17 +14,30 @@ local spawn = { } ---@param cmd string -local function exepath(cmd) +---@param path? string +local function exepath(cmd, path) + local function get_exepath(cmd) + if path then + local old_path = vim.env.PATH + vim.env.PATH = path + local expanded_cmd = vim.fn.exepath(cmd) + vim.env.PATH = old_path + return expanded_cmd + else + return vim.fn.exepath(cmd) + end + end + if platform.is.win then -- On Windows, exepath() assumes the system is capable of executing "Unix-like" executables if the shell is a Unix -- shell. We temporarily override it to a Windows shell ("powershell") to avoid that behaviour. local old_shell = vim.o.shell vim.o.shell = "powershell" - local expanded_cmd = vim.fn.exepath(cmd) + local expanded_cmd = get_exepath(cmd) vim.o.shell = old_shell return expanded_cmd else - return vim.fn.exepath(cmd) + return get_exepath(cmd) end end @@ -41,7 +54,7 @@ local function Failure(err, cmd) })) end -local has_path = _.any(_.starts_with "PATH=") +local get_path_from_env_list = _.compose(_.strip_prefix "PATH=", _.find_first(_.starts_with "PATH=")) ---@class SpawnArgs ---@field with_paths string[]? Paths to add to the PATH environment variable. @@ -80,9 +93,9 @@ setmetatable(spawn, { -- Find the executable path via vim.fn.exepath on Windows because libuv fails to resolve certain executables -- in PATH. - if platform.is.win and (spawn_args.env and has_path(spawn_args.env)) == nil then + if platform.is.win then a.scheduler() - local expanded_cmd = exepath(canonical_cmd) + local expanded_cmd = exepath(canonical_cmd, spawn_args.env and get_path_from_env_list(spawn_args.env)) if expanded_cmd ~= "" then cmd = expanded_cmd end -- cgit v1.2.3-70-g09d2