Skip to content

Commit

Permalink
feat: ensure plugin runtime paths are available before rocks initiali…
Browse files Browse the repository at this point in the history
…ses (#285)

* feat: ensure plugin runtime paths are available before rocks initialises

* tests(integration): run on all platforms

* tests(integration): add test for setting the colorscheme in init.lua

* tests(integration): add linux and macos cpath entries

* tests(integration): check for success file

* tests(integration): tweak colorscheme test

---------

Co-authored-by: vhyrro <76052559+vhyrro@users.noreply.github.com>
  • Loading branch information
mrcjkb and vhyrro authored Apr 24, 2024
1 parent c969b61 commit 462379d
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
-- init.lua used for integration tests
vim.g.rocks_nvim = {
rocks_path = vim.fs.joinpath(vim.fn.getcwd(), "rocks"),
_log_level = vim.log.levels.TRACE,
Expand All @@ -10,6 +11,10 @@ local luarocks_path = {
package.path = package.path .. ";" .. table.concat(luarocks_path, ";")

local luarocks_cpath = {
vim.fs.joinpath(vim.g.rocks_nvim.rocks_path, "lib", "lua", "5.1", "?.so"),
vim.fs.joinpath(vim.g.rocks_nvim.rocks_path, "lib64", "lua", "5.1", "?.so"),
vim.fs.joinpath(vim.g.rocks_nvim.rocks_path, "lib", "lua", "5.1", "?.dylib"),
vim.fs.joinpath(vim.g.rocks_nvim.rocks_path, "lib64", "lua", "5.1", "?.dylib"),
vim.fs.joinpath(vim.g.rocks_nvim.rocks_path, "lib", "lua", "5.1", "?.dll"),
vim.fs.joinpath(vim.g.rocks_nvim.rocks_path, "lib64", "lua", "5.1", "?.dll"),
}
Expand Down
8 changes: 8 additions & 0 deletions .github/resources/install-colorscheme.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
local done = false
require("rocks.api").install("sweetie.nvim", "2.4.0", function()
vim.uv.sleep(2000) -- Leave time for symlinks to be created
done = true
end)
vim.fn.wait(60000, function()
return done and 1 or 0
end)
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
---
name: Windows test
# An impure test case to help debug issues with rocks.nvim on windows
name: Integration tests
# Impure, cross platform integration tests
on:
pull_request:
# We only want to manually trigger this as needed
workflow_dispatch:

jobs:
build:
runs-on: windows-2019
test:
runs-on: ${{ matrix.os.host }}
strategy:
matrix:
os:
- host: ubuntu-20.04
- host: windows-2019
- host: macos-11 # x86_64
- host: macos-14 # aarch64
steps:
- uses: actions/checkout@v4
- name: Install C/C++ Compiler
Expand Down Expand Up @@ -38,7 +44,14 @@ jobs:
shell: bash
run: |
ls rocks/lib/lua/5.1
nvim -u .github/resources/init-windows.lua -c "lua print('OK')" +q
nvim -u .github/resources/init-integration.lua -l .github/resources/install-colorscheme.lua +q
ls rocks
# Will fail if rocks.log does not exist
cat rocks/rocks.log
echo "vim.cmd.colorscheme('sweetie')" >> .github/resources/init-integration.lua
echo "vim.cmd.e('success')" >> .github/resources/init-integration.lua
nvim -u .github/resources/init-integration.lua -c +wq
if [ ! -f success ]; then
echo "Integration test failed!"
exit 1
fi
108 changes: 83 additions & 25 deletions lua/rocks/adapter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,70 +11,112 @@
--
-- License: GPLv3
-- Created: 13 Mar 2024
-- Updated: 13 Mar 2024
-- Updated: 19 Apr 2024
-- Homepage: https://github.com/nvim-neorocks/rocks.nvim
-- Maintainers: NTBBloodbath <bloodbathalchemist@protonmail.com>, Vhyrro <vhyrro@gmail.com>, mrcjkb <marc@jakobi.dev>

local adapter = {}

local nio = require("nio")
local log = require("rocks.log")
local fs = require("rocks.fs")
local config = require("rocks.config.internal")

local rtp_link_dir = vim.fs.joinpath(config.rocks_path, "rocks_rtp")
vim.opt.runtimepath:append(rtp_link_dir)

local rocks_parser_dir = vim.fs.joinpath(config.rocks_path, "lib", "lua", "5.1", "parser")
local data_dir = vim.fn.stdpath("data")
---@cast data_dir string
local site_link_dir = vim.fs.joinpath(data_dir, "site", "pack", "luarocks", "opt")

--- Initialise the rocks_rtp directory
---@return boolean success
local function init_rocks_rtp_dir()
if not vim.uv.fs_stat(rtp_link_dir) and vim.fn.mkdir(rtp_link_dir, "p") ~= 1 then
log.error("Failed to create rocks_rtp symlink directory.")
return false
end
return true
end
local rocks_parser_dir = vim.fs.joinpath(config.rocks_path, "lib", "lua", "5.1", "parser")

---@type async fun(symlink_dir_name: string, dest_dir_path: string)
local add_rtp_symlink = nio.create(function(symlink_dir_name, dest_dir_path)
local symlink_dir_path = vim.fs.joinpath(rtp_link_dir, symlink_dir_name)
---@type async fun(symlink_location: string, symlink_dir_name: string, dest_dir_path: string)
local create_symlink = nio.create(function(symlink_location, symlink_dir_name, dest_dir_path)
local symlink_dir_path = vim.fs.joinpath(symlink_location, symlink_dir_name)
-- NOTE: nio.uv.fs_stat behaves differently than vim.uv.fs_stat
if not vim.uv.fs_stat(symlink_dir_path) then
log.info("Creating symlink directory: " .. symlink_dir_name)
nio.uv.fs_symlink(dest_dir_path, symlink_dir_path)
end
end, 2)
end, 3)

---@param symlink_dir string
local function validate_symlink_dir(symlink_dir)
if not vim.uv.fs_stat(symlink_dir) and not vim.uv.fs_unlink(symlink_dir) then
log.error("Failed to remove symlink: " .. symlink_dir)
end
end

--- Check if the tree-sitter parser symlink is valid,
--- and remove it if it isn't
function adapter.validate_tree_sitter_parser_symlink()
validate_symlink_dir(vim.fs.joinpath(rtp_link_dir, "parser"))
end

--- Neovim doesn't support `:checkhealth` for luarocks plugins.
--- To work around this, we create a symlink in the `rocks_path` that
--- we add to the runtimepath, so that Neovim can find health files.
local function init_checkhealth_symlink()
local rocks_lua_dir = vim.fs.joinpath(config.rocks_path, "share", "lua", "5.1")
if vim.uv.fs_stat(rocks_lua_dir) then
add_rtp_symlink("lua", rocks_lua_dir)
create_symlink(rtp_link_dir, "lua", rocks_lua_dir)
end
end

--- If any tree-sitter parsers are installed,
-- initialise a symlink so that Neovim can find them.
function adapter.init_tree_sitter_parser_symlink()
if vim.uv.fs_stat(rocks_parser_dir) then
add_rtp_symlink("parser", rocks_parser_dir)
create_symlink(rtp_link_dir, "parser", rocks_parser_dir)
end
end

--- Check if the tree-sitter parser symlink is valid,
--- and remove it if it isn't
function adapter.validate_tree_sitter_parser_symlink()
local symlink_dir_path = vim.fs.joinpath(rtp_link_dir, "parser")
if not vim.uv.fs_stat(rocks_parser_dir) and not vim.uv.fs_unlink(symlink_dir_path) then
log.error("Failed to remove 'parser' symlink: " .. symlink_dir_path)
--- Check if the site symlinks are valid,
--- and remove them if they aren't
function adapter.validate_site_symlinks()
local handle = vim.uv.fs_scandir(site_link_dir)
while handle do
local name, ty = vim.uv.fs_scandir_next(handle)
if not name then
return
end
if ty == "link" then
validate_symlink_dir(vim.fs.joinpath(site_link_dir, name))
end
end
end

function adapter.init()
local ok = init_rocks_rtp_dir()
--- @param rock Rock
local function init_site_symlink(rock)
local rock_dir = vim.fs.joinpath(config.rocks_path, "lib", "luarocks", "rocks-5.1", rock.name)
local handle = vim.uv.fs_scandir(rock_dir)
while handle do
local name, ty = vim.uv.fs_scandir_next(handle)
if not name then
return
end
if ty == "directory" and name:find("^" .. rock.version) ~= nil then
local rock_version_dir = vim.fs.joinpath(rock_dir, name)
create_symlink(site_link_dir, rock.name, rock_version_dir)
return
end
end
end

--- Loop over the installed rocks and create symlinks in site/pack/luarocks/opt,
--- so that rtp paths like 'autoload' and 'color' are available before rocks.nvim
--- has initialised.
adapter.init_site_symlinks = nio.create(function()
local state = require("rocks.state")
for _, rock in pairs(state.installed_rocks()) do
init_site_symlink(rock)
end
end)

--- Initialise/validate runtimepath symlinks for tree-sitter parsers and health checks
local function init_rtp_links()
local ok = fs.mkdir_p(rtp_link_dir)
if not ok then
return
end
Expand All @@ -83,4 +125,20 @@ function adapter.init()
adapter.init_tree_sitter_parser_symlink()
end

--- Initialise/validate site symlinks so that 'autoload' and 'colors', etc.
--- are available on the rtp (without sourcing plugins) before rocks.nvim is loaded.
local function init_site_links()
local ok = fs.mkdir_p(site_link_dir)
if not ok then
return
end
adapter.validate_site_symlinks()
adapter.init_site_symlinks()
end

function adapter.init()
init_rtp_links()
init_site_links()
end

return adapter
25 changes: 24 additions & 1 deletion lua/rocks/fs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ end
---@param contents string file contents
function fs.write_file(location, mode, contents)
local dir = vim.fn.fnamemodify(location, ":h")
vim.fn.mkdir(dir, "p")
fs.mkdir_p(dir)
-- 644 sets read and write permissions for the owner, and it sets read-only
-- mode for the group and others
uv.fs_open(location, mode, tonumber("644", 8), function(err, file)
Expand Down Expand Up @@ -81,6 +81,29 @@ function fs.read_or_create(location, default)
return content
end

---Create directory, including parents
---@param dir string
---@return boolean success
function fs.mkdir_p(dir)
local mode = 493
local mod = ""
local path = dir
while vim.fn.isdirectory(path) == 0 do
mod = mod .. ":h"
path = vim.fn.fnamemodify(dir, mod)
end
while mod ~= "" do
mod = string.sub(mod, 3)
path = vim.fn.fnamemodify(dir, mod)
vim.uv.fs_mkdir(path, mode)
end
if not vim.uv.fs_stat(dir) then
log.error("Failed to create directory: " .. dir)
return false
end
return true
end

return fs

--- fs.lua ends here
9 changes: 5 additions & 4 deletions lua/rocks/operations/helpers.lua
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
---@mod rocks.operations.helpers
--
-- Copyright (C) 2023 Neorocks Org.
-- Copyright (C) 2024 Neorocks Org.
--
-- Version: 0.1.0
-- License: GPLv3
-- Created: 07 Mar 2024
-- Updated: 07 Mar 2024
-- Updated: 19 Apr 2024
-- Homepage: https://github.com/nvim-neorocks/rocks.nvim
-- Maintainers: NTBBloodbath <bloodbathalchemist@protonmail.com>, Vhyrro <vhyrro@gmail.com>, mrcjkb <marc@jakobi.dev>
--
Expand Down Expand Up @@ -86,9 +85,10 @@ helpers.install = function(rock_spec, progress_handle)
progress_handle:report({ message = message })
end

adapter.init_tree_sitter_parser_symlink()
adapter.init_site_symlinks()
if config.dynamic_rtp and not rock_spec.opt then
runtime.packadd(name)
adapter.init_tree_sitter_parser_symlink()
end

future.set(installed_rock)
Expand Down Expand Up @@ -127,6 +127,7 @@ helpers.remove = function(name, progress_handle)
future.set(sc)
end
adapter.validate_tree_sitter_parser_symlink()
adapter.validate_site_symlinks()
end)
return future
end
Expand Down
9 changes: 9 additions & 0 deletions spec/fs_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
local fs = require("rocks.fs")
local tempdir = vim.fn.tempname()
describe("rocks.fs", function()
it("mkdir_p", function()
local dir = vim.fs.joinpath(tempdir, "bar", "baz", "bat")
fs.mkdir_p(dir)
assert.is_not_nil(vim.uv.fs_stat(dir))
end)
end)

0 comments on commit 462379d

Please sign in to comment.