aboutsummaryrefslogtreecommitdiffstats
path: root/lua
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2026-05-30 15:34:55 +0200
committerGitHub <noreply@github.com>2026-05-30 15:34:55 +0200
commit8838e7acf07679fb717246518d2b83cbe3a1078e (patch)
tree6d67c637efa021d41b8d21b1e9223fc63468d8c0 /lua
parentchore(main): release 2.3.0 (#2072) (diff)
downloadmason-8838e7acf07679fb717246518d2b83cbe3a1078e.tar
mason-8838e7acf07679fb717246518d2b83cbe3a1078e.tar.gz
mason-8838e7acf07679fb717246518d2b83cbe3a1078e.tar.bz2
mason-8838e7acf07679fb717246518d2b83cbe3a1078e.tar.lz
mason-8838e7acf07679fb717246518d2b83cbe3a1078e.tar.xz
mason-8838e7acf07679fb717246518d2b83cbe3a1078e.tar.zst
mason-8838e7acf07679fb717246518d2b83cbe3a1078e.zip
fix(fs): implement rmrf natively via libuv (#2098)
Diffstat (limited to 'lua')
-rw-r--r--lua/mason-core/fs.lua66
-rw-r--r--lua/mason-core/installer/InstallRunner.lua2
-rw-r--r--lua/mason-core/installer/context/InstallContextFs.lua2
3 files changed, 62 insertions, 8 deletions
diff --git a/lua/mason-core/fs.lua b/lua/mason-core/fs.lua
index e7f8343f..5decd3ca 100644
--- a/lua/mason-core/fs.lua
+++ b/lua/mason-core/fs.lua
@@ -36,6 +36,43 @@ local function make_module(uv)
end
---@param path string
+ ---@param fn fun(abs_path: string, entry: string, type: "directory" | "file")
+ function M.ls(path, fn)
+ local handle = vim.uv.fs_scandir(path)
+ while handle do
+ local entry, t = vim.uv.fs_scandir_next(handle)
+ if not entry then
+ break
+ end
+
+ ---@type string
+ local abs_path
+ if vim.fn.has "win32" == 1 and path:sub(1, 4) == [[\\?\]] then
+ -- Extended-length paths are used, we cannot use vim.fs.joinpath.
+ abs_path = path .. "\\" .. entry
+ else
+ abs_path = vim.fs.joinpath(path, entry)
+ end
+ t = t or vim.uv.fs_stat(abs_path).type
+
+ if fn(abs_path, entry, t) == false then
+ break
+ end
+ end
+ end
+
+ ---@param path string
+ ---@param fn fun(abs_path: string, entry: string, type: "directory" | "file")
+ function M.walk(path, fn)
+ M.ls(path, function(abs_path, entry, type)
+ if type == "directory" then
+ M.walk(abs_path, fn)
+ end
+ fn(abs_path, entry, type)
+ end)
+ end
+
+ ---@param path string
function M.rmrf(path)
assert(
Path.is_subdirectory(settings.current.install_root_dir, path),
@@ -45,13 +82,30 @@ local function make_module(uv)
)
)
log.debug("fs: rmrf", path)
- if vim.in_fast_event() then
- a.scheduler()
- end
- if vim.fn.delete(path, "rf") ~= 0 then
- log.debug "fs: rmrf failed"
- error(("rmrf: Could not remove directory %q."):format(path))
+ if vim.fn.has "win32" == 1 then
+ -- Use extended-length path (ELP) on Windows. We have no easy way to check if the current system has
+ -- LongPathsEnabled, so we enforce extended-length paths always.
+ --
+ -- This is currently only done in this function (rmrf) because we walk the entire file tree under `path`,
+ -- which may result in deeply nested file paths that exceed MAX_PATH (260 characters). Other fs operations
+ -- don't reach so deeply into the file tree and pose minimal risk of exceeding the MAX_PATH.
+ -- NOTE: When using the ELP prefix Windows doesn't normalize file paths, meaning path separators (\) need to
+ -- be correct.
+ --
+ -- See https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation
+ local extended_length_prefix = [[\\?\]]
+ path = extended_length_prefix .. path:gsub("/", "\\")
end
+ M.walk(path, function(abs_path, _, type)
+ if type == "directory" then
+ log.trace("fs: rmdir", abs_path)
+ vim.uv.fs_rmdir(abs_path)
+ else
+ log.trace("fs: unlink", abs_path)
+ vim.uv.fs_unlink(abs_path)
+ end
+ end)
+ M.rmdir(path)
end
---@param path string
diff --git a/lua/mason-core/installer/InstallRunner.lua b/lua/mason-core/installer/InstallRunner.lua
index 336f0c93..497ac644 100644
--- a/lua/mason-core/installer/InstallRunner.lua
+++ b/lua/mason-core/installer/InstallRunner.lua
@@ -78,7 +78,7 @@ function InstallRunner:execute(opts, callback)
if not opts.debug and not success then
-- clean up installation dir
pcall(function()
- fs.async.rmrf(context.cwd:get())
+ fs.sync.rmrf(context.cwd:get())
end)
end
diff --git a/lua/mason-core/installer/context/InstallContextFs.lua b/lua/mason-core/installer/context/InstallContextFs.lua
index 93379017..c473c0a9 100644
--- a/lua/mason-core/installer/context/InstallContextFs.lua
+++ b/lua/mason-core/installer/context/InstallContextFs.lua
@@ -51,7 +51,7 @@ end
---@async
---@param rel_path string The relative path from the current working directory.
function InstallContextFs:rmrf(rel_path)
- return fs.async.rmrf(path.concat { self.cwd:get(), rel_path })
+ return fs.sync.rmrf(path.concat { self.cwd:get(), rel_path })
end
---@async