forked from williamboman/mason-lspconfig.nvim
-
Notifications
You must be signed in to change notification settings - Fork 0
/
init.lua
140 lines (125 loc) · 4.28 KB
/
init.lua
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
local process = require "mason-core.process"
local path = require "mason-core.path"
local platform = require "mason-core.platform"
local spawn = require "mason-core.spawn"
local a = require "mason-core.async"
local Optional = require "mason-core.optional"
local installer = require "mason-core.installer"
local client = require "mason-core.managers.cargo.client"
local _ = require "mason-core.functional"
local get_bin_path = _.compose(path.concat, function(executable)
return _.append(executable, { "bin" })
end, _.if_else(_.always(platform.is.win), _.format "%s.exe", _.identity))
---@param crate string
local function with_receipt(crate)
return function()
local ctx = installer.context()
ctx.receipt:with_primary_source(ctx.receipt.cargo(crate))
end
end
local M = {}
---@async
---@param crate string The crate to install.
---@param opts {git: boolean | string, features: string|nil, bin: string[] | nil } | nil
function M.crate(crate, opts)
return function()
M.install(crate, opts).with_receipt()
end
end
---@async
---@param crate string The crate to install.
---@param opts {git: boolean | string, features: string|nil, bin: string[] | nil } | nil
function M.install(crate, opts)
local ctx = installer.context()
opts = opts or {}
ctx.requested_version:if_present(function()
assert(not opts.git, "Providing a version when installing a git crate is not allowed.")
end)
local final_crate = crate
if opts.git then
final_crate = { "--git" }
if type(opts.git) == "string" then
table.insert(final_crate, opts.git)
end
table.insert(final_crate, crate)
end
ctx.spawn.cargo {
"install",
"--root",
".",
"--locked",
ctx.requested_version
:map(function(version)
return { "--version", version }
end)
:or_else(vim.NIL),
opts.features and { "--features", opts.features } or vim.NIL,
final_crate,
}
if opts.bin then
_.each(function(bin)
ctx:link_bin(bin, get_bin_path(bin))
end, opts.bin)
end
return {
with_receipt = with_receipt(crate),
}
end
---@param output string: The `cargo install --list` output.
---@return table<string, string>: Key is the crate name, value is its version.
function M.parse_installed_crates(output)
local installed_crates = {}
for _, line in ipairs(vim.split(output, "\n")) do
local name, version = line:match "^(.+)%s+v([.%S]+)[%s:]"
if name and version then
installed_crates[name] = version
end
end
return installed_crates
end
---@async
---@param receipt InstallReceipt
---@param install_dir string
function M.check_outdated_primary_package(receipt, install_dir)
return M.get_installed_primary_package_version(receipt, install_dir):map_catching(function(installed_version)
---@type CrateResponse
local crate_response = client.fetch_crate(receipt.primary_source.package):get_or_throw()
if installed_version ~= crate_response.crate.max_stable_version then
return {
name = receipt.primary_source.package,
current_version = installed_version,
latest_version = crate_response.crate.max_stable_version,
}
else
error "Primary package is not outdated."
end
end)
end
---@async
---@param receipt InstallReceipt
---@param install_dir string
function M.get_installed_primary_package_version(receipt, install_dir)
return spawn
.cargo({
"install",
"--list",
"--root",
".",
cwd = install_dir,
})
:map_catching(function(result)
local installed_crates = M.parse_installed_crates(result.stdout)
if vim.in_fast_event() then
a.scheduler() -- needed because vim.fn.* call
end
local pkg = vim.fn.fnamemodify(receipt.primary_source.package, ":t")
return Optional.of_nilable(installed_crates[pkg]):or_else_throw "Failed to find cargo package version."
end)
end
---@param install_dir string
function M.env(install_dir)
return {
PATH = process.extend_path { path.concat { install_dir, "bin" } },
}
end
return M