bug: Duplicated plugins when case mismatch
Did you check docs and existing issues?
- [x] I have read all the lazy.nvim docs
- [x] I have updated the plugin to the latest version before submitting this issue
- [x] I have searched the existing issues of lazy.nvim
- [x] I have searched the existing issues of plugins related to this issue
Neovim version (nvim -v)
NVIM v0.10.4 Build type: RelWithDebInfo LuaJIT 2.1.1736781742
Operating system/version
Arch Linux
Describe the bug
When a plugin is declared a second time with misspelled case, the plugin is duplicated without warning. This can cause some weird behaviour that isn't immediately obvious how to resolve.
I suppose this is an issue only on case-sensitive filesystems.
Steps To Reproduce
nvim -u repro.lua(see below)ls .repro/data/nvim/lazy- notice two checkouts of "tokyonight.nvim"
Expected Behavior
Preferably, no duplication is allowed and lazy would just understand to look in the correct folder regardless of the case. This could be done by:
- canonicalising all plugin checkouts to lower case (probably breaking change)
- doing a case-insensitive search in the data directory and selecting the already checked out folder
At the very least a warning should be emitted, maybe even an error.
Repro
vim.env.LAZY_STDPATH = ".repro"
load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()
require("lazy.minit").repro({
spec = {
{ "folke/tokyonight.nvim" },
{ "folke/Tokyonight.nvim" },
},
})
Duplicate #1228
The should be case-sensitive. Won't change this. Could lead to issues on case-sensitive file systems otherwise
The issue though is that the lack of case-insensitivity (CI) is causing issues on case-sensitive (CS) filesystems.
Given two plugin names;
require("lazy.minit").repro({
spec = {
{ name = "user/plugin.nvim" },
{ name = "user/PLUGIN.NVIM" },
},
})
The github urls are CI, so both of these resolve to the same repo. It's not possible to use case do differentiate them. When cloning, git will use the last path as the target folder, respecting the case. On CS filesystems, this results in two different folders, on CI systems it results in one, the case of which is determined by the first one cloned.
I don't know how the internals of lazy.nvim work, but I see a couple of problematic situations, assuming the created folder is created via git clone <url>:
- fs is CS and lazy does CS matching of
names- there are two clone
- there are two plugin configurations
lazy.nvimwill consider that "user/plugin.nvim" and "user/PLUGIN.nvim" are two separate plugins- this is unexpected
- fs is CI and lazy does CS matching of
namess- there is one clone
- there are two plugin configurations
- although there's only one checkout, the configurations are not merged
- this is unexpected
- fs is CS and lazy does CI matching of
names- there are two clone
- there is one merged plugin configuration
- lazy will properly merge the configurations, but an unused repo is also cloned
- although working as expected, creates an unused checkout
- fs is CI and lazy does CI matching of
names- there is one clone
- there is one merged plugin configuration
- lazy will work as expected
IMO, this should be handled somehow. Even if it is just a warning that says "duplicate plugin name detected" and then carries on.
Doubt it based on maintainer's last reply regarding this. In the end, it's the user's responsibility in my personal opinion to not make spelling mistakes.
When maintainer is back from vacation (#1934), he will give his personal opinion on this.
PS: also doing git clone https://github.com/L3MON4D3/LuaSnip and https://github.com/L3MON4D3/luasnip results in 2 folders, so I guess lazy.nvim operates accordingly. (but i guess that might have to do with my filesystem)
PS: also doing git clone https://github.com/L3MON4D3/LuaSnip and https://github.com/L3MON4D3/luasnip results in 2 folders, so I guess lazy.nvim operates accordingly.
Indeed, but only on CS filesystems. And having two clones is not an issue, it is then adding both of them to the rtp that is.
But still, on CI fs, the merged configuration issue remains and is just as hard to debug.
When maintainer is back from vacation (#1934), he will give his personal opinion on this.
Yep. And thanks for triaging this, I didn't see the other issue.
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.
Waiting for @folke to comment.
I have experienced the similar problem from a different perspective.
The current state of things
- Plugins are indexed using
nameproperty from the Spec; - If the
nameis not provided, it is generated from the repository name in formnvim-telescope/telescope.nvimbecomestelescope_nvim.
The problem
According to the documentation, name is very handy to use throughout the config enabling short user-friendly references like the following:
return {
{ "nvim-telescope/telescope.nvim", name = "telescope" },
{ "chrisgrieser/nvim-tinygit", dependencies = { "telescope" } },
}
However, a plugin may provide a dependency configuration in its own. In this example, the chrisgrieser/nvim-tinygit provides dependencies through lazy.lua in a simple manner, without a name; as it would be expected.
This leads to two installations of Telescope, one in the telescope directory as the name states, and another one in telescope.nvim directory as the Tinygit's lazy.lua states, and Lazy would also show telescope and telescope.nvim in the UI.
Depending on various lazy loading handlers (cmd and keys) on of this plugins will load first. If the first called is Tinygit, Telescope loads with the default configuration.
Repro
This is bare minimum reproduction that shows only two plugins cloned but the loading appears to be correct.
vim.env.LAZY_STDPATH = ".repro"
load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()
require("lazy.minit").repro({
spec = {
{ "nvim-telescope/telescope.nvim", name = "telescope" },
{ "chrisgrieser/nvim-tinygit" },
},
})
Below is a more complex example but it does not really make the point as Tinygit used Telescope in an unknown to me way (lazy does not track importing from either plugin):
vim.env.LAZY_STDPATH = ".repro"
load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()
require("lazy.minit").repro({
spec = {
{
"nvim-telescope/telescope.nvim",
name = "telescope",
cmd = "Telescope",
opts = {
defaults = {
mappings = {
i = {
["<esc>"] = "close",
},
},
},
},
},
{
"chrisgrieser/nvim-tinygit",
cmd = "Tinygit",
},
},
})
Conclusion
I agree with the argument that it's the responsibility of the user to provide uniform configuration. In this example, parts of the configuration are provided by third parties.
There is no way to instruct Lazy that the plugin in dependencies of other plugin is the same as in the user's config if the name was changed. On the other hand, Lazy does not create a uniform index of plugins taking into account all keys (to the best of my knowledge, url and version) but relies purely on name.
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.