diff --git a/README.md b/README.md index e1a3c412f..4c8a99185 100644 --- a/README.md +++ b/README.md @@ -388,6 +388,7 @@ use { requires = string or list, -- Specifies plugin dependencies. See "dependencies". rocks = string or list, -- Specifies Luarocks dependencies for the plugin config = string or function, -- Specifies code to run after this plugin is loaded. + override = boolean, -- Specifies if a plugin using a names the same should be overriden by this one -- The setup key implies opt = true setup = string or function, -- Specifies code to run before this plugin is loaded. The code is ran even if -- the plugin is waiting for other conditions (ft, cond...) to be met. diff --git a/lua/packer.lua b/lua/packer.lua index ff2b93a67..b7e2c181e 100644 --- a/lua/packer.lua +++ b/lua/packer.lua @@ -342,6 +342,8 @@ end local function manage_all_plugins() local log = require_and_configure 'log' log.debug 'Processing plugin specs' + local plugin_utils = require_and_configure 'plugin_utils' + plugin_specifications = plugin_utils.replace_overrides(plugin_specifications) if plugins == nil or next(plugins) == nil then for _, spec in ipairs(plugin_specifications) do manage(spec) diff --git a/lua/packer/plugin_utils.lua b/lua/packer/plugin_utils.lua index f7ec8780c..65befa38d 100644 --- a/lua/packer/plugin_utils.lua +++ b/lua/packer/plugin_utils.lua @@ -284,4 +284,25 @@ plugin_utils.post_update_hook = function(plugin, disp) end) end +plugin_utils.replace_overrides = function(plugins_specifications) + local installed_plugins_indexes = {} + local new_plugins_specifications = {} + for plugins_specifications_index, specified_plugins in ipairs(plugins_specifications) do + local new_specification = {} + for specification_index, plugin in ipairs(specified_plugins.spec) do + local plugin_short_name = util.get_plugin_short_name(plugin) + if not installed_plugins_indexes[plugin_short_name] then + installed_plugins_indexes[plugin_short_name] = specification_index + new_specification[#new_specification + 1] = plugin + elseif true == plugin.override then + local plugin_index = installed_plugins_indexes[plugin_short_name] + new_specification[plugin_index] = plugin + end + end + new_plugins_specifications[plugins_specifications_index] = + { line = specified_plugins.line, spec = new_specification } + end + return new_plugins_specifications +end + return plugin_utils diff --git a/tests/plugin_utils_spec.lua b/tests/plugin_utils_spec.lua index 3c73b3bd6..da67775c7 100644 --- a/tests/plugin_utils_spec.lua +++ b/tests/plugin_utils_spec.lua @@ -1,39 +1,42 @@ -local a = require('plenary.async_lib.tests') +local a = require 'plenary.async_lib.tests' local await = require('packer.async').wait local async = require('packer.async').sync -local plugin_utils = require('packer.plugin_utils') -local helpers = require("tests.helpers") +local plugin_utils = require 'packer.plugin_utils' +local helpers = require 'tests.helpers' local fmt = string.format a.describe('Plugin utils -', function() - a.describe('find_missing_plugins', function() - local repo_name = "test.nvim" + local repo_name = 'test.nvim' local path - plugin_utils.cfg({start_dir = helpers.base_dir}) + plugin_utils.cfg { start_dir = helpers.base_dir } - before_each(function() path = helpers.create_git_dir(repo_name) end) + before_each(function() + path = helpers.create_git_dir(repo_name) + end) - after_each(function() helpers.cleanup_dirs("tmp/packer") end) + after_each(function() + helpers.cleanup_dirs 'tmp/packer' + end) a.it('should pick up plugins with a different remote URL', function() local test_repo_name = fmt('user2/%s', repo_name) local plugins = { [repo_name] = { opt = false, - type = "git", - name = fmt("user1/%s", repo_name), + type = 'git', + name = fmt('user1/%s', repo_name), short_name = repo_name, remote_url = function() return async(function() - return {ok = {remote = fmt('https://github.com/%s', test_repo_name)}} + return { ok = { remote = fmt('https://github.com/%s', test_repo_name) } } end) - end - } + end, + }, } - local result = await(plugin_utils.find_missing_plugins(plugins, {}, {[path] = true})) + local result = await(plugin_utils.find_missing_plugins(plugins, {}, { [path] = true })) assert.truthy(result) assert.equal(1, #vim.tbl_keys(result)) end) @@ -43,17 +46,17 @@ a.describe('Plugin utils -', function() local plugins = { [repo_name] = { opt = false, - type = "git", + type = 'git', name = test_repo_name, short_name = repo_name, remote_url = function() return async(function() - return {ok = {remote = fmt('https://github.com/%s', test_repo_name)}} + return { ok = { remote = fmt('https://github.com/%s', test_repo_name) } } end) - end - } + end, + }, } - local result = await(plugin_utils.find_missing_plugins(plugins, {}, {[path] = true})) + local result = await(plugin_utils.find_missing_plugins(plugins, {}, { [path] = true })) assert.truthy(result) assert.equal(0, #result) end) @@ -63,19 +66,71 @@ a.describe('Plugin utils -', function() local plugins = { [repo_name] = { opt = false, - type = "git", - name = fmt("user1/%s", repo_name), + type = 'git', + name = fmt('user1/%s', repo_name), short_name = repo_name, remote_url = function() return async(function() - return {ok = {remote = fmt('git@github.com:%s.git', test_repo_name)}} + return { ok = { remote = fmt('git@github.com:%s.git', test_repo_name) } } end) - end - } + end, + }, } - local result = await(plugin_utils.find_missing_plugins(plugins, {}, {[path] = true})) + local result = await(plugin_utils.find_missing_plugins(plugins, {}, { [path] = true })) assert.truthy(result) assert.equal(1, #vim.tbl_keys(result)) end) end) + + a.describe('override_plugins', function() + plugin_utils.cfg { start_dir = helpers.base_dir } + + a.it('should replace overriden plugin (override after overriden)', function() + local overriden_repository_name = 'test/nvim' + local repository_override_name = fmt('override/%s', overriden_repository_name) + local plugins_specifications = { + { + line = 0, + spec = { + { + overriden_repository_name, + url = fmt('https://test.nvim/%s', overriden_repository_name), + }, + { + repository_override_name, + override = true, + }, + }, + }, + } + local result = plugin_utils.replace_overrides(plugins_specifications) + assert.equal(#result[1].spec, 1) + assert.equal(repository_override_name, result[1].spec[1][1]) + assert.equal(true, result[1].spec[1].override) + end) + + a.it('replace_overrides should replace overriden plugin (override before overriden)', function() + local overriden_repository_name = 'test/nvim' + local repository_override_name = fmt('override/%s', overriden_repository_name) + local plugins_specifications = { + { + line = 0, + spec = { + { + repository_override_name, + override = true, + }, + { + overriden_repository_name, + url = fmt('https://test.nvim/%s', overriden_repository_name), + }, + }, + }, + } + local result = plugin_utils.replace_overrides(plugins_specifications) + assert.equal(#result[1].spec, 1) + assert.equal(repository_override_name, result[1].spec[1][1]) + assert.equal(true, result[1].spec[1].override) + end) + end) end)