From c94d35309ffe59603510e8b25a728b994c83d3b4 Mon Sep 17 00:00:00 2001 From: Simi Falaye Date: Thu, 31 Oct 2024 15:02:15 -0600 Subject: [PATCH] feat(api): Add support for install options --- .github/workflows/luarocks.yml | 2 +- lua/rocks/api/init.lua | 7 ++- lua/rocks/operations/add.lua | 6 ++- lua/rocks/operations/helpers/init.lua | 36 +++++++++++++- lua/rocks/operations/pin.lua | 2 +- lua/rocks/operations/unpin.lua | 2 +- lua/rocks/operations/update.lua | 7 +-- rocks.nvim-scm-1.rockspec | 4 +- spec/operations/helpers_spec.lua | 67 +++++++++++++++++++++++++++ 9 files changed, 119 insertions(+), 14 deletions(-) diff --git a/.github/workflows/luarocks.yml b/.github/workflows/luarocks.yml index b81baa96..9a2515cc 100644 --- a/.github/workflows/luarocks.yml +++ b/.github/workflows/luarocks.yml @@ -32,7 +32,7 @@ jobs: test_interpreters: "" dependencies: | luarocks >= 3.11.1, < 4.0.0 - toml-edit >= 0.5.0 + toml-edit >= 0.6.0 fidget.nvim >= 1.1.0 fzy nvim-nio diff --git a/lua/rocks/api/init.lua b/lua/rocks/api/init.lua index a4783475..298b074c 100644 --- a/lua/rocks/api/init.lua +++ b/lua/rocks/api/init.lua @@ -188,12 +188,15 @@ function api.source_runtime_dir(dir) require("rtp_nvim").source_rtp_dir(dir) end +---@class InstallRockOpts: rocks.AddOpts + ---Invoke ':Rocks install' with a callback ---@param rock_name rock_name #The rock name ---@param version? string The version of the rock to use ---@param callback? fun(rock: Rock) Invoked upon successful completion -function api.install(rock_name, version, callback) - operations.add({ rock_name, version }, callback) +---@param opts? InstallRockOpts Installation options +function api.install(rock_name, version, callback, opts) + operations.add({ rock_name, version }, callback, opts --[[@as rocks.AddOpts]]) end return api diff --git a/lua/rocks/operations/add.lua b/lua/rocks/operations/add.lua index 47206bc5..d366b59b 100644 --- a/lua/rocks/operations/add.lua +++ b/lua/rocks/operations/add.lua @@ -63,6 +63,7 @@ end ---@class rocks.AddOpts ---@field skip_prompts? boolean Whether to skip any "search 'dev' manifest prompts ---@field cmd? 'install' | 'update' Command used to invoke this function. Default: `'install'` +---@field config_path? string Config file path to use for installing the rock relative to the base config file --- Adds a new rock and updates the `rocks.toml` file ---@param arg_list string[] #Argument list, potentially used by external handlers. The first argument is the package, e.g. the rock name @@ -87,8 +88,9 @@ add.add = function(arg_list, callback, opts) nio.run(function() helpers.semaphore.with(function() - local user_rocks = helpers.parse_rocks_toml() - local handler = handlers.get_install_handler_callback(user_rocks, arg_list) + local user_rocks = opts.config_path and helpers.parse_import_rocks_toml(opts.config_path) + or helpers.parse_rocks_toml() + local handler = handlers.get_install_handler_callback(user_rocks --[[@as MutRocksTomlRef]], arg_list) if type(handler) == "function" then local function report_progress(message) progress_handle:report({ diff --git a/lua/rocks/operations/helpers/init.lua b/lua/rocks/operations/helpers/init.lua index e21f80ec..92635387 100644 --- a/lua/rocks/operations/helpers/init.lua +++ b/lua/rocks/operations/helpers/init.lua @@ -31,7 +31,7 @@ local helpers = {} helpers.semaphore = nio.control.semaphore(1) ---Decode the user rocks from rocks.toml, creating a default config file if it does not exist ----@return MutRocksTomlRef +---@return MultiMutRocksTomlWrapper function helpers.parse_rocks_toml() local rocks_toml_configs = {} config.read_rocks_toml(function(file_str) @@ -44,7 +44,39 @@ function helpers.parse_rocks_toml() table.insert(rocks_toml_configs, rocks_toml_config) end) - return multi_mut_rocks_toml_wrapper.new(rocks_toml_configs) --[[@as MutRocksTomlRef]] + return multi_mut_rocks_toml_wrapper.new(rocks_toml_configs) +end + +---Decode the rocks from an imported rocks.toml config, creating a default config file if it does not exist +---@type async fun(config_path:string?): MultiMutRocksTomlWrapper +function helpers.parse_import_rocks_toml(config_path) + local base_config_file = fs.read_or_create(config.config_path, constants.DEFAULT_CONFIG) + local base_rocks_toml = require("toml_edit").parse(base_config_file) + local config_file_path = vim.fs.dirname(config.config_path) + if config_file_path == config.config_path then + return multi_mut_rocks_toml_wrapper.new({ { config = base_rocks_toml, path = config.config_path } }) + end + local config_file = fs.read_or_create(vim.fs.joinpath(config_file_path, config_path), "") + + if base_rocks_toml.import then + local i = 0 + while true do + i = i + 1 + if not base_rocks_toml.import[i] then + base_rocks_toml.import[i] = config_path + break + elseif base_rocks_toml.import[i] == config_path then + break + end + end + else + base_rocks_toml.import = { config_path } + end + fs.write_file_await(config.config_path, "w", tostring(base_rocks_toml)) + + return multi_mut_rocks_toml_wrapper.new({ + { config = require("toml_edit").parse(config_file), path = config_file_path }, + }) end ---@param rocks_toml MutRocksTomlRef diff --git a/lua/rocks/operations/pin.lua b/lua/rocks/operations/pin.lua index eae513fc..a02826c9 100644 --- a/lua/rocks/operations/pin.lua +++ b/lua/rocks/operations/pin.lua @@ -24,7 +24,7 @@ pin.pin = function(rock_name) nio.run(function() helpers.semaphore.with(function() local user_config = helpers.parse_rocks_toml() - local rocks_key, user_rock = helpers.get_rock_and_key(user_config, rock_name) + local rocks_key, user_rock = helpers.get_rock_and_key(user_config --[[@as MutRocksTomlRef]], rock_name) if not rocks_key then vim.schedule(function() vim.notify(rock_name .. " not found in rocks.toml", vim.log.levels.ERROR) diff --git a/lua/rocks/operations/unpin.lua b/lua/rocks/operations/unpin.lua index 27217fe2..0c2fa5b9 100644 --- a/lua/rocks/operations/unpin.lua +++ b/lua/rocks/operations/unpin.lua @@ -24,7 +24,7 @@ unpin.unpin = function(rock_name) nio.run(function() helpers.semaphore.with(function() local user_config = helpers.parse_rocks_toml() - local rocks_key, user_rock = helpers.get_rock_and_key(user_config, rock_name) + local rocks_key, user_rock = helpers.get_rock_and_key(user_config --[[@as MutRocksTomlRef]], rock_name) if not rocks_key or not user_rock then vim.schedule(function() vim.notify(rock_name .. " not found in rocks.toml", vim.log.levels.ERROR) diff --git a/lua/rocks/operations/update.lua b/lua/rocks/operations/update.lua index e762166a..18ece2e3 100644 --- a/lua/rocks/operations/update.lua +++ b/lua/rocks/operations/update.lua @@ -93,7 +93,7 @@ update.update = function(on_complete, opts) ---@param key rock_name ---@param rock OutdatedRock function(acc, key, rock) - local _, user_rock = helpers.get_rock_and_key(user_rocks, rock.name) + local _, user_rock = helpers.get_rock_and_key(user_rocks --[[@as MutRocksTomlRef]], rock.name) if user_rock and not user_rock.pin then acc[key] = rock end @@ -108,7 +108,7 @@ update.update = function(on_complete, opts) if config.reinstall_dev_rocks_on_update then to_update = add_dev_rocks_for_update(to_update) end - local external_update_handlers = handlers.get_update_handler_callbacks(user_rocks) + local external_update_handlers = handlers.get_update_handler_callbacks(user_rocks --[[@as MutRocksTomlRef]]) local total_update_count = #to_update + #external_update_handlers @@ -161,7 +161,8 @@ update.update = function(on_complete, opts) for _, installed_rock in pairs(state.installed_rocks()) do ---@type rock_name local rock_name = installed_rock.name - local rocks_key, user_rock = helpers.get_rock_and_key(user_rocks, installed_rock.name) + local rocks_key, user_rock = + helpers.get_rock_and_key(user_rocks --[[@as MutRocksTomlRef]], installed_rock.name) if user_rock and user_rock.version then -- Rock is configured as a table -> Update version. user_rocks[rocks_key][rock_name].version = installed_rock.version diff --git a/rocks.nvim-scm-1.rockspec b/rocks.nvim-scm-1.rockspec index 57199aa2..bb199973 100644 --- a/rocks.nvim-scm-1.rockspec +++ b/rocks.nvim-scm-1.rockspec @@ -9,7 +9,7 @@ version = _MODREV .. _SPECREV dependencies = { "lua >= 5.1", "luarocks >= 3.11.1, < 4.0.0", - "toml-edit >= 0.5.0", + "toml-edit >= 0.6.0", "fidget.nvim >= 1.1.0", "fzy", "nvim-nio", @@ -19,7 +19,7 @@ dependencies = { test_dependencies = { "lua >= 5.1", "luarocks >= 3.11.1, < 4.0.0", - "toml-edit >= 0.5.0", + "toml-edit >= 0.6.0", "fidget.nvim >= 1.1.0", "fzy", "nvim-nio", diff --git a/spec/operations/helpers_spec.lua b/spec/operations/helpers_spec.lua index e90cd6cc..265496f7 100644 --- a/spec/operations/helpers_spec.lua +++ b/spec/operations/helpers_spec.lua @@ -122,6 +122,73 @@ pin = true assert.same(nil, rocks_toml.luarocks.servers[3]) assert.is_not_nil(rocks_toml.import) end) + nio.tests.it("Parse import rocks toml passing base config path", function() + local config_content = [[ +[rocks] +myrock = "1.0.0" +]] + + local fh = assert(io.open(config.config_path, "w"), "Could not open rocks.toml for writing") + fh:write(config_content) + fh:close() + + local rocks_toml = helpers.parse_rocks_toml(config.config_path) + assert.is_not_nil(rocks_toml.rocks) + assert.same("1.0.0", rocks_toml.rocks.myrock) + end) + nio.tests.it("Parse import rocks toml append to imports", function() + local config_content = [[ +import = ["other-rocks.toml"] + +[rocks] +myrock = "1.0.0" +]] + + local fh = assert(io.open(config.config_path, "w"), "Could not open rocks.toml for writing") + fh:write(config_content) + fh:close() + + local _ = helpers.parse_import_rocks_toml("local-rocks.toml") + + -- Validate that new file was created + fh = assert( + io.open(vim.fs.joinpath(tempdir, "local-rocks.toml"), "r"), + "Expected local rocks.toml to be created. Could not open for reading" + ) + fh:close() + -- Validate that import was added to rocks toml + fh = assert(io.open(config.config_path, "r"), "Could not open rocks.toml for reading") + local result_config_content = fh:read("*a") + assert.is_not_nil(string.find(result_config_content, 'import = %["other%-rocks%.toml", "local%-rocks%.toml"%]')) + fh:close() + end) + nio.tests.it("Parse import rocks toml create imports with existing import file", function() + local config_content = [[ +[rocks] +myrock = "1.0.0" +]] + local config_content2 = [[ +[rocks] +mylocalrock = "1.0.0" +]] + local fh = assert(io.open(config.config_path, "w"), "Could not open rocks.toml for writing") + fh:write(config_content) + fh:close() + fh = assert( + io.open(vim.fs.joinpath(tempdir, "local-rocks.toml"), "w"), + "Could not open local rocks.toml for writing" + ) + fh:write(config_content2) + fh:close() + + local _ = helpers.parse_import_rocks_toml("local-rocks.toml") + + -- Validate imports was created + fh = assert(io.open(config.config_path, "r"), "Could not open rocks.toml for reading") + local result_config_content = fh:read("*a") + assert.is_not_nil(string.find(result_config_content, 'import = %["local%-rocks%.toml"%]')) + fh:close() + end) end) describe("operations.helpers.multi_mut_rocks_toml_wrapper", function()