1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
local Path = require "mason-core.path"
local a = require "mason-core.async"
local log = require "mason-core.log"
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/mason-org/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 new_path string
---@param flags table? { excl?: boolean, ficlone?: boolean, ficlone_force?: boolean }
function M.copy_file(path, new_path, flags)
log.debug("fs: copy_file", path, new_path, flags)
uv.fs_copyfile(path, new_path, flags)
end
---@param path string
---@param contents string
---@param flags string? Defaults to "w".
function M.write_file(path, contents, flags)
log.trace("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
if entries[i].name and not entries[i].type then
-- See https://github.com/luvit/luv/issues/660
local full_path = Path.concat { path, entries[i].name }
log.trace("fs: fs_readdir falling back to fs_stat to find type", full_path)
local stat = uv.fs_stat(full_path)
entries[i].type = stat.type
end
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
---@param path string
---@param new_path string
function M.symlink(path, new_path)
log.trace("fs: symlink", path, new_path)
uv.fs_symlink(path, new_path)
end
---@param path string
---@param mode integer
function M.chmod(path, mode)
log.trace("fs: chmod", path, mode)
uv.fs_chmod(path, mode)
end
return M
end
return {
async = make_module(require "mason-core.async.uv"),
sync = make_module(vim.loop),
}
|