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
|
local _ = require "mason-core.functional"
local process = require "mason-core.process"
local path = require "mason-core.path"
local Result = require "mason-core.result"
local spawn = require "mason-core.spawn"
local Optional = require "mason-core.optional"
local installer = require "mason-core.installer"
local platform = require "mason-core.platform"
local M = {}
local create_bin_path = _.compose(path.concat, function(executable)
return _.append(executable, { "vendor", "bin" })
end, _.if_else(_.always(platform.is.win), _.format "%s.bat", _.identity))
---@param packages string[]
local function with_receipt(packages)
return function()
local ctx = installer.context()
ctx.receipt:with_primary_source(ctx.receipt.composer(packages[1]))
for i = 2, #packages do
ctx.receipt:with_secondary_source(ctx.receipt.composer(packages[i]))
end
end
end
---@async
---@param packages { [number]: string, bin: string[] | nil } @The composer packages to install. The first item in this list will be the recipient of the requested version, if set.
function M.packages(packages)
return function()
return M.require(packages).with_receipt()
end
end
---@async
---@param packages { [number]: string, bin: string[] | nil } @The composer packages to install. The first item in this list will be the recipient of the requested version, if set.
function M.require(packages)
local ctx = installer.context()
local pkgs = _.list_copy(packages)
if not ctx.fs:file_exists "composer.json" then
ctx.spawn.composer { "init", "--no-interaction", "--stability=stable" }
end
ctx.requested_version:if_present(function(version)
pkgs[1] = ("%s:%s"):format(pkgs[1], version)
end)
ctx.spawn.composer { "require", pkgs }
if packages.bin then
_.each(function(executable)
ctx:link_bin(executable, create_bin_path(executable))
end, packages.bin)
end
return {
with_receipt = with_receipt(packages),
}
end
---@async
function M.install()
local ctx = installer.context()
ctx.spawn.composer {
"install",
"--no-interaction",
"--no-dev",
"--optimize-autoloader",
"--classmap-authoritative",
}
end
---@async
---@param receipt InstallReceipt
---@param install_dir string
function M.check_outdated_primary_package(receipt, install_dir)
if receipt.primary_source.type ~= "composer" then
return Result.failure "Receipt does not have a primary source of type composer"
end
return spawn
.composer({
"outdated",
"--no-interaction",
"--format=json",
cwd = install_dir,
})
:map_catching(function(result)
local outdated_packages = vim.json.decode(result.stdout)
local outdated_package = _.find_first(function(pkg)
return pkg.name == receipt.primary_source.package
end, outdated_packages.installed)
return Optional.of_nilable(outdated_package)
:map(function(pkg)
if pkg.version ~= pkg.latest then
return {
name = pkg.name,
current_version = pkg.version,
latest_version = pkg.latest,
}
end
end)
:or_else_throw "Primary package is not outdated."
end)
end
---@async
---@param receipt InstallReceipt
---@param install_dir string
function M.get_installed_primary_package_version(receipt, install_dir)
if receipt.primary_source.type ~= "composer" then
return Result.failure "Receipt does not have a primary source of type composer"
end
return spawn
.composer({
"info",
"--format=json",
receipt.primary_source.package,
cwd = install_dir,
})
:map_catching(function(result)
local info = vim.json.decode(result.stdout)
return info.versions[1]
end)
end
---@param install_dir string
function M.env(install_dir)
return {
PATH = process.extend_path { path.concat { install_dir, "vendor", "bin" } },
}
end
return M
|