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
178
179
|
local a = require "mason-core.async"
local installer = require "mason-core.installer"
local fetch = require "mason-core.fetch"
local platform = require "mason-core.platform"
local powershell = require "mason-core.managers.powershell"
local path = require "mason-core.path"
local Result = require "mason-core.result"
local M = {}
local function with_system_executable_receipt(executable)
return function()
local ctx = installer.context()
ctx.receipt:with_primary_source(ctx.receipt.system(executable))
end
end
---@async
---@param executable string
---@param opts {help_url:string?}?
function M.ensure_executable(executable, opts)
local ctx = installer.context()
opts = opts or {}
if vim.in_fast_event() then
a.scheduler()
end
if vim.fn.executable(executable) ~= 1 then
ctx.stdio_sink.stderr(("%s was not found in path.\n"):format(executable))
if opts.help_url then
ctx.stdio_sink.stderr(("See %s for installation instructions.\n"):format(opts.help_url))
end
error("Installation failed: system executable was not found.", 0)
end
return {
with_receipt = with_system_executable_receipt(executable),
}
end
---@async
---@param url string
---@param out_file string
function M.download_file(url, out_file)
local ctx = installer.context()
ctx.stdio_sink.stdout(("Downloading file %q...\n"):format(url))
fetch(url, {
out_file = path.concat { ctx.cwd:get(), out_file },
})
:map_err(function(err)
return ("Failed to download file %q.\n%s"):format(url, err)
end)
:get_or_throw()
end
---@async
---@param file string
---@param dest string
function M.unzip(file, dest)
local ctx = installer.context()
platform.when {
unix = function()
ctx.spawn.unzip { "-d", dest, file }
end,
win = function()
powershell.command(
("Microsoft.PowerShell.Archive\\Expand-Archive -Path %q -DestinationPath %q"):format(file, dest),
{},
ctx.spawn
)
end,
}
pcall(function()
-- make sure the .zip archive doesn't linger
ctx.fs:unlink(file)
end)
end
---@param file string
local function win_extract(file)
local ctx = installer.context()
Result.run_catching(function()
ctx.spawn["7z"] { "x", "-y", "-r", file }
end)
:recover_catching(function()
ctx.spawn.peazip { "-ext2here", path.concat { ctx.cwd:get(), file } } -- peazip requires absolute paths
end)
:recover_catching(function()
ctx.spawn.wzunzip { file }
end)
:recover_catching(function()
ctx.spawn.winrar { "e", file }
end)
:get_or_throw(("Unable to unpack %s."):format(file))
end
---@async
---@param file string
---@param opts {strip_components:integer}?
function M.untar(file, opts)
opts = opts or {}
local ctx = installer.context()
ctx.spawn.tar {
opts.strip_components and { "--strip-components", opts.strip_components } or vim.NIL,
"--no-same-owner",
"-xvf",
file,
}
pcall(function()
ctx.fs:unlink(file)
end)
end
---@async
---@param file string
---@param opts {strip_components: integer?}?
function M.untarxz(file, opts)
opts = opts or {}
local ctx = installer.context()
platform.when {
unix = function()
M.untar(file, opts)
end,
win = function()
Result.run_catching(function()
win_extract(file) -- unpack .tar.xz to .tar
local uncompressed_tar = file:gsub(".xz$", "")
M.untar(uncompressed_tar, opts)
end):recover(function()
ctx.spawn.arc {
"unarchive",
opts.strip_components and { "--strip-components", opts.strip_components } or vim.NIL,
file,
}
pcall(function()
ctx.fs:unlink(file)
end)
end)
end,
}
end
---@async
---@param file string
function M.gunzip(file)
platform.when {
unix = function()
local ctx = installer.context()
ctx.spawn.gzip { "-d", file }
end,
win = function()
win_extract(file)
end,
}
end
---@async
---@param flags string The chmod flag to apply.
---@param files string[] A list of relative paths to apply the chmod on.
function M.chmod(flags, files)
if platform.is_unix then
local ctx = installer.context()
ctx.spawn.chmod { flags, files }
end
end
---@async
---Wrapper around vim.ui.select.
---@param items table
---@params opts
function M.select(items, opts)
assert(not platform.is_headless, "Tried to prompt for user input while in headless mode.")
if vim.in_fast_event() then
a.scheduler()
end
local async_select = a.promisify(vim.ui.select)
return async_select(items, opts)
end
return M
|