aboutsummaryrefslogtreecommitdiffstats
path: root/lua/mason-core/fs.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/mason-core/fs.lua')
-rw-r--r--lua/mason-core/fs.lua152
1 files changed, 152 insertions, 0 deletions
diff --git a/lua/mason-core/fs.lua b/lua/mason-core/fs.lua
new file mode 100644
index 00000000..a69b5de5
--- /dev/null
+++ b/lua/mason-core/fs.lua
@@ -0,0 +1,152 @@
+local log = require "mason-core.log"
+local a = require "mason-core.async"
+local Path = require "mason-core.path"
+local settings = require "mason.settings"
+
+local function make_module(uv)
+ local M = {}
+
+ ---@param path string
+ function M.fstat(path)
+ log.trace("fs: fstat", path)
+ local fd = uv.fs_open(path, "r", 438)
+ local fstat = uv.fs_fstat(fd)
+ uv.fs_close(fd)
+ return fstat
+ end
+
+ ---@param path string
+ function M.file_exists(path)
+ log.trace("fs: file_exists", path)
+ local ok, fstat = pcall(M.fstat, path)
+ if not ok then
+ return false
+ end
+ return fstat.type == "file"
+ end
+
+ ---@param path string
+ function M.dir_exists(path)
+ log.trace("fs: dir_exists", path)
+ local ok, fstat = pcall(M.fstat, path)
+ if not ok then
+ return false
+ end
+ return fstat.type == "directory"
+ end
+
+ ---@param path string
+ function M.rmrf(path)
+ assert(
+ Path.is_subdirectory(settings.current.install_root_dir, path),
+ (
+ "Refusing to rmrf %q which is outside of the allowed boundary %q. Please report this error at https://github.com/williamboman/mason.nvim/issues/new"
+ ):format(path, settings.current.install_root_dir)
+ )
+ 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))
+ end
+ end
+
+ ---@param path string
+ function M.unlink(path)
+ log.debug("fs: unlink", path)
+ uv.fs_unlink(path)
+ end
+
+ ---@param path string
+ function M.mkdir(path)
+ log.debug("fs: mkdir", path)
+ uv.fs_mkdir(path, 493) -- 493(10) == 755(8)
+ end
+
+ ---@param path string
+ function M.mkdirp(path)
+ log.debug("fs: mkdirp", path)
+ if vim.in_fast_event() then
+ a.scheduler()
+ end
+ if vim.fn.mkdir(path, "p") ~= 1 then
+ log.debug "fs: mkdirp failed"
+ error(("mkdirp: Could not create directory %q."):format(path))
+ end
+ end
+
+ ---@param path string
+ ---@param new_path string
+ function M.rename(path, new_path)
+ log.debug("fs: rename", path, new_path)
+ uv.fs_rename(path, new_path)
+ end
+
+ ---@param path string
+ ---@param contents string
+ ---@param flags string|nil @Defaults to "w".
+ function M.write_file(path, contents, flags)
+ log.debug("fs: write_file", path)
+ local fd = uv.fs_open(path, flags or "w", 438)
+ uv.fs_write(fd, contents, -1)
+ uv.fs_close(fd)
+ end
+
+ ---@param path string
+ ---@param contents string
+ function M.append_file(path, contents)
+ M.write_file(path, contents, "a")
+ end
+
+ ---@param path string
+ function M.read_file(path)
+ log.trace("fs: read_file", path)
+ local fd = uv.fs_open(path, "r", 438)
+ local fstat = uv.fs_fstat(fd)
+ local contents = uv.fs_read(fd, fstat.size, 0)
+ uv.fs_close(fd)
+ return contents
+ end
+
+ ---@alias ReaddirEntry {name: string, type: string}
+
+ ---@param path string @The full path to the directory to read.
+ ---@return ReaddirEntry[]
+ function M.readdir(path)
+ log.trace("fs: fs_opendir", path)
+ local dir = assert(vim.loop.fs_opendir(path, nil, 25))
+ local all_entries = {}
+ local exhausted = false
+
+ repeat
+ local entries = uv.fs_readdir(dir)
+ log.trace("fs: fs_readdir", path, entries)
+ if entries and #entries > 0 then
+ for i = 1, #entries do
+ all_entries[#all_entries + 1] = entries[i]
+ end
+ else
+ log.trace("fs: fs_readdir exhausted scan", path)
+ exhausted = true
+ end
+ until exhausted
+
+ uv.fs_closedir(dir)
+
+ return all_entries
+ end
+
+ function M.symlink(path, new_path)
+ log.trace("fs: symlink", path, new_path)
+ uv.fs_symlink(path, new_path)
+ end
+
+ return M
+end
+
+return {
+ async = make_module(require "mason-core.async.uv"),
+ sync = make_module(vim.loop),
+}