diff options
| author | William Boman <william@redwill.se> | 2022-07-08 18:34:38 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-07-08 18:34:38 +0200 |
| commit | 976aa4fbee8a070f362cab6f6ec84e9251a90cf9 (patch) | |
| tree | 5e8d9c9c59444a25c7801b8f39763c4ba6e1f76d /lua/mason-core/installer/linker.lua | |
| parent | feat: add gotests, gomodifytags, impl (#28) (diff) | |
| download | mason-976aa4fbee8a070f362cab6f6ec84e9251a90cf9.tar mason-976aa4fbee8a070f362cab6f6ec84e9251a90cf9.tar.gz mason-976aa4fbee8a070f362cab6f6ec84e9251a90cf9.tar.bz2 mason-976aa4fbee8a070f362cab6f6ec84e9251a90cf9.tar.lz mason-976aa4fbee8a070f362cab6f6ec84e9251a90cf9.tar.xz mason-976aa4fbee8a070f362cab6f6ec84e9251a90cf9.tar.zst mason-976aa4fbee8a070f362cab6f6ec84e9251a90cf9.zip | |
refactor: add mason-schemas and mason-core modules (#29)
* refactor: add mason-schemas and move generated filetype map to mason-lspconfig
* refactor: add mason-core module
Diffstat (limited to 'lua/mason-core/installer/linker.lua')
| -rw-r--r-- | lua/mason-core/installer/linker.lua | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/lua/mason-core/installer/linker.lua b/lua/mason-core/installer/linker.lua new file mode 100644 index 00000000..0419f392 --- /dev/null +++ b/lua/mason-core/installer/linker.lua @@ -0,0 +1,84 @@ +local path = require "mason-core.path" +local platform = require "mason-core.platform" +local _ = require "mason-core.functional" +local log = require "mason-core.log" +local fs = require "mason-core.fs" + +local M = {} + +---@param pkg Package +---@param links InstallReceiptLinks +local function unlink_bin(pkg, links) + for executable in pairs(links.bin) do + local bin_path = path.bin_prefix(executable) + fs.sync.unlink(bin_path) + end +end + +---@param pkg Package +---@param links InstallReceiptLinks +function M.unlink(pkg, links) + log.fmt_debug("Unlinking %s", pkg) + unlink_bin(pkg, links) +end + +---@param to string +local function relative_path_from_bin(to) + local _, match_end = to:find(path.install_prefix(), 1, true) + assert(match_end, "Failed to produce relative path.") + local relative_path = to:sub(match_end + 1) + return ".." .. relative_path +end + +---@async +---@param context InstallContext +local function link_bin(context) + local links = context.receipt.links.bin + local pkg = context.package + for name, rel_path in pairs(links) do + local target_abs_path = path.concat { pkg:get_install_path(), rel_path } + local target_rel_path = relative_path_from_bin(target_abs_path) + local bin_path = path.bin_prefix(name) + + assert(not fs.async.file_exists(bin_path), ("bin/%s is already linked."):format(name)) + assert(fs.async.file_exists(target_abs_path), ("Link target %q does not exist."):format(target_abs_path)) + + log.fmt_debug("Linking bin %s to %s", name, target_rel_path) + + platform.when { + unix = function() + fs.async.symlink(target_rel_path, bin_path) + end, + win = function() + -- We don't "symlink" on Windows because: + -- 1) .LNK is not commonly found in PATHEXT + -- 2) some executables can only run from their true installation location + -- 3) many utilities only consider .COM, .EXE, .CMD, .BAT files as candidates by default when resolving executables (e.g. neovim's |exepath()| and |executable()|) + fs.async.write_file( + ("%s.cmd"):format(bin_path), + _.dedent(([[ + @ECHO off + GOTO start + :find_dp0 + SET dp0=%%~dp0 + EXIT /b + :start + SETLOCAL + CALL :find_dp0 + + endLocal & goto #_undefined_# 2>NUL || title %%COMSPEC%% & "%%dp0%%\%s" %%* + ]]):format(target_rel_path)) + ) + end, + } + end +end + +---@async +---@param context InstallContext +function M.link(context) + log.fmt_debug("Linking %s", context.package) + link_bin(context) +end + +return M |
