114 lines
3.5 KiB
Lua
114 lines
3.5 KiB
Lua
-- lua/nuwiki/install.lua — install / build the `nuwiki-ls` binary.
|
|
--
|
|
-- Strategy:
|
|
-- 1. Look for `bin/nuwiki-ls[.exe]` next to the plugin.
|
|
-- 2. If missing or `g:nuwiki_build_from_source` is set, build with cargo.
|
|
-- 3. Otherwise try to download a release asset for the current target.
|
|
-- On failure, fall back to cargo.
|
|
|
|
local M = {}
|
|
|
|
local function plugin_root()
|
|
local source = debug.getinfo(1, 'S').source:sub(2)
|
|
return vim.fn.fnamemodify(source, ':h:h:h')
|
|
end
|
|
|
|
local function exe_suffix()
|
|
return vim.fn.has('win32') == 1 and '.exe' or ''
|
|
end
|
|
|
|
function M.expected_path()
|
|
return plugin_root() .. '/bin/nuwiki-ls' .. exe_suffix()
|
|
end
|
|
|
|
function M.is_installed()
|
|
return vim.fn.executable(M.expected_path()) == 1
|
|
end
|
|
|
|
local function target_triple()
|
|
if vim.fn.has('win32') == 1 then
|
|
return 'x86_64-pc-windows-msvc'
|
|
elseif vim.fn.has('mac') == 1 then
|
|
if vim.fn.has('arm64') == 1 or jit and jit.arch == 'arm64' then
|
|
return 'aarch64-apple-darwin'
|
|
end
|
|
return 'x86_64-apple-darwin'
|
|
elseif vim.fn.has('linux') == 1 then
|
|
local uname = vim.uv and vim.uv.os_uname() or vim.loop.os_uname()
|
|
local musl = (vim.fn.system('ldd --version 2>&1'):find('musl') ~= nil)
|
|
if uname.machine == 'aarch64' or uname.machine == 'arm64' then
|
|
return musl and 'aarch64-unknown-linux-musl' or 'aarch64-unknown-linux-gnu'
|
|
end
|
|
return musl and 'x86_64-unknown-linux-musl' or 'x86_64-unknown-linux-gnu'
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local function build_from_source(dest)
|
|
if vim.fn.executable('cargo') ~= 1 then
|
|
vim.notify('nuwiki: cargo not found, cannot build from source',
|
|
vim.log.levels.ERROR)
|
|
return false
|
|
end
|
|
local root = plugin_root()
|
|
vim.notify('nuwiki: building from source (cargo build --release) …', vim.log.levels.INFO)
|
|
local _ = vim.fn.system({
|
|
'cargo', 'build', '--release', '-p', 'nuwiki-ls',
|
|
'--manifest-path', root .. '/Cargo.toml',
|
|
})
|
|
if vim.v.shell_error ~= 0 then
|
|
vim.notify('nuwiki: cargo build failed', vim.log.levels.ERROR)
|
|
return false
|
|
end
|
|
local built = root .. '/target/release/nuwiki-ls' .. exe_suffix()
|
|
vim.fn.system({ 'cp', built, dest })
|
|
vim.fn.system({ 'chmod', '+x', dest })
|
|
return vim.fn.executable(dest) == 1
|
|
end
|
|
|
|
local function download_release(dest)
|
|
local target = target_triple()
|
|
if not target then
|
|
return false
|
|
end
|
|
if vim.fn.executable('curl') ~= 1 or vim.fn.executable('tar') ~= 1 then
|
|
return false
|
|
end
|
|
local url = string.format(
|
|
'https://code.gfran.co/gffranco/nuwiki/releases/latest/download/nuwiki-ls-%s.tar.gz',
|
|
target
|
|
)
|
|
local archive = vim.fn.tempname() .. '.tar.gz'
|
|
vim.fn.system({ 'curl', '-fsSL', '-o', archive, url })
|
|
if vim.v.shell_error ~= 0 then
|
|
return false
|
|
end
|
|
local extract = vim.fn.tempname()
|
|
vim.fn.mkdir(extract, 'p')
|
|
vim.fn.system({ 'tar', '-xzf', archive, '-C', extract })
|
|
if vim.v.shell_error ~= 0 then
|
|
return false
|
|
end
|
|
vim.fn.system({ 'cp', extract .. '/nuwiki-ls' .. exe_suffix(), dest })
|
|
vim.fn.system({ 'chmod', '+x', dest })
|
|
return vim.fn.executable(dest) == 1
|
|
end
|
|
|
|
function M.install()
|
|
local dest = M.expected_path()
|
|
vim.fn.mkdir(vim.fn.fnamemodify(dest, ':h'), 'p')
|
|
|
|
if vim.g.nuwiki_build_from_source == 1 then
|
|
return build_from_source(dest)
|
|
end
|
|
if download_release(dest) then
|
|
vim.notify('nuwiki: installed ' .. dest, vim.log.levels.INFO)
|
|
return true
|
|
end
|
|
vim.notify('nuwiki: download failed, falling back to source build',
|
|
vim.log.levels.WARN)
|
|
return build_from_source(dest)
|
|
end
|
|
|
|
return M
|