|
1 | 1 | local logging = require('please.logging') |
2 | 2 | local plz = require('please.plz') |
| 3 | +local runner = require('please.runner') |
3 | 4 |
|
4 | 5 | local M = {} |
5 | 6 |
|
@@ -111,4 +112,110 @@ function M.output(root, target) |
111 | 112 | return output |
112 | 113 | end |
113 | 114 |
|
| 115 | +---Determines the appropriate GOROOT for a repo and passes it to the given callback. |
| 116 | +---The result is passed to a callback because a target may need to be built to create the GOROOT. Progress will be shown |
| 117 | +---in a floating window in this case. |
| 118 | +---Determining the GOROOT may fail. In this case, the callback will be passed `nil`, `errmsg`. |
| 119 | +---@param root string absolute path to the repo root |
| 120 | +---@param cb fun(goroot:string?, errmsg:string?) function called on success or error |
| 121 | +function M.with_goroot(root, cb) |
| 122 | + logging.log_call('query.go_root') |
| 123 | + |
| 124 | + local gotool = 'go' |
| 125 | + local gotools, err = M.config(root, 'plugin.go.gotool') |
| 126 | + if gotools then |
| 127 | + gotool = gotools[1] |
| 128 | + elseif not (err or ''):match('Settable field not defined') then |
| 129 | + cb(nil, string.format('determining GOROOT: %s', err)) |
| 130 | + return |
| 131 | + end |
| 132 | + |
| 133 | + if vim.startswith(gotool, ':') or vim.startswith(gotool, '//') then |
| 134 | + gotool = gotool:gsub('|go$', '') |
| 135 | + local gotool_output, err = M.output(root, gotool) |
| 136 | + if not gotool_output then |
| 137 | + cb(nil, string.format('determining GOROOT: %s', gotool, err)) |
| 138 | + return |
| 139 | + end |
| 140 | + local rel_goroot = vim.trim(gotool_output) |
| 141 | + local goroot = vim.fs.joinpath(root, rel_goroot) |
| 142 | + if not vim.uv.fs_stat(goroot) then |
| 143 | + local msg = logging.format( |
| 144 | + 'GOROOT "%s" for repository "%s" does not exist. Build plugin.go.gotool target "%s" to create it?', |
| 145 | + rel_goroot, |
| 146 | + root, |
| 147 | + gotool |
| 148 | + ) |
| 149 | + local ok, result = pcall(vim.fn.confirm, msg, '&Yes\n&No', 1, 'Question') |
| 150 | + if not ok and result ~= 'Keyboard interrupt' then |
| 151 | + error(result) |
| 152 | + end |
| 153 | + local build = ok and result == 1 |
| 154 | + if not build then |
| 155 | + cb(nil, string.format('determining GOROOT: GOROOT "%s" for repository "%s" does not exist', rel_goroot, root)) |
| 156 | + return |
| 157 | + end |
| 158 | + runner.Runner.start(root, { 'build', gotool }, { |
| 159 | + on_exit = function(success, runner) |
| 160 | + if success then |
| 161 | + runner:minimise() |
| 162 | + logging.info('built plugin.go.gotool target "%s" successfully', gotool) |
| 163 | + cb(goroot) |
| 164 | + else |
| 165 | + cb(nil, string.format('determining GOROOT: building plugin.go.gotool target "%s" failed', gotool)) |
| 166 | + end |
| 167 | + end, |
| 168 | + }) |
| 169 | + return |
| 170 | + end |
| 171 | + cb(goroot) |
| 172 | + return |
| 173 | + end |
| 174 | + |
| 175 | + if vim.startswith(gotool, '/') then |
| 176 | + if not vim.uv.fs_stat(gotool) then |
| 177 | + cb(nil, string.format('determining GOROOT: plugin.go.gotool "%s" does not exist', gotool)) |
| 178 | + return |
| 179 | + end |
| 180 | + local goroot_res = vim.system({ gotool, 'env', 'GOROOT' }):wait() |
| 181 | + if goroot_res.code == 0 then |
| 182 | + cb(vim.trim(goroot_res.stdout)) |
| 183 | + return |
| 184 | + else |
| 185 | + cb(nil, string.format('determining GOROOT: %s env GOROOT: %s', gotool, goroot_res.stderr)) |
| 186 | + return |
| 187 | + end |
| 188 | + end |
| 189 | + |
| 190 | + local build_paths, err = M.config(root, 'build.path') |
| 191 | + if not build_paths then |
| 192 | + cb(nil, string.format('determining GOROOT: %s', err)) |
| 193 | + return |
| 194 | + end |
| 195 | + for _, build_path in ipairs(build_paths) do |
| 196 | + for path in vim.gsplit(build_path, ':') do |
| 197 | + local go = vim.fs.joinpath(path, gotool) |
| 198 | + if vim.uv.fs_stat(go) then |
| 199 | + local goroot_res = vim.system({ go, 'env', 'GOROOT' }):wait() |
| 200 | + if goroot_res.code == 0 then |
| 201 | + cb(vim.trim(goroot_res.stdout)) |
| 202 | + return |
| 203 | + else |
| 204 | + cb(nil, string.format('determining GOROOT: %s env GOROOT: %s', go, goroot_res.stderr)) |
| 205 | + return |
| 206 | + end |
| 207 | + end |
| 208 | + end |
| 209 | + end |
| 210 | + |
| 211 | + cb( |
| 212 | + nil, |
| 213 | + string.format( |
| 214 | + 'determining GOROOT: plugin.go.gotool "%s" not found in build.path "%s"', |
| 215 | + gotool, |
| 216 | + table.concat(build_paths, ':') |
| 217 | + ) |
| 218 | + ) |
| 219 | +end |
| 220 | + |
114 | 221 | return M |
0 commit comments