aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2025-05-19 05:58:01 +0200
committerGitHub <noreply@github.com>2025-05-19 05:58:01 +0200
commit3501b0f96d9f2f878b1947cf3614bc02d053a0c0 (patch)
tree5f9025e2df9652346fcd74b7186be1c5a6366367
parentfix(spawn): fix calling vim.fn when inside fast event loop on Windows (#1950) (diff)
downloadmason-3501b0f96d9f2f878b1947cf3614bc02d053a0c0.tar
mason-3501b0f96d9f2f878b1947cf3614bc02d053a0c0.tar.gz
mason-3501b0f96d9f2f878b1947cf3614bc02d053a0c0.tar.bz2
mason-3501b0f96d9f2f878b1947cf3614bc02d053a0c0.tar.lz
mason-3501b0f96d9f2f878b1947cf3614bc02d053a0c0.tar.xz
mason-3501b0f96d9f2f878b1947cf3614bc02d053a0c0.tar.zst
mason-3501b0f96d9f2f878b1947cf3614bc02d053a0c0.zip
fix(registry): ensure there's no duplicate registry entries (#1957)
-rw-r--r--lua/mason-registry/init.lua4
-rw-r--r--lua/mason-registry/sources/file.lua5
-rw-r--r--lua/mason-registry/sources/github.lua5
-rw-r--r--lua/mason-registry/sources/init.lua52
-rw-r--r--lua/mason-registry/sources/lua.lua5
-rw-r--r--tests/mason-registry/sources/collection_spec.lua21
6 files changed, 88 insertions, 4 deletions
diff --git a/lua/mason-registry/init.lua b/lua/mason-registry/init.lua
index 713335f0..535e6b57 100644
--- a/lua/mason-registry/init.lua
+++ b/lua/mason-registry/init.lua
@@ -103,16 +103,16 @@ end
---@param callback? fun(success: boolean, updated_registries: RegistrySource[])
function Registry.update(callback)
- log.debug "Updating the registry."
local a = require "mason-core.async"
local installer = require "mason-registry.installer"
local noop = function() end
a.run(function()
if installer.channel then
- log.trace "Registry update already in progress."
+ log.debug "Registry update already in progress."
return installer.channel:receive():get_or_throw()
else
+ log.debug "Updating the registry."
Registry:emit("update:start", Registry.sources)
return installer
.install(Registry.sources, function(finished, all)
diff --git a/lua/mason-registry/sources/file.lua b/lua/mason-registry/sources/file.lua
index 34c855c0..663efaaa 100644
--- a/lua/mason-registry/sources/file.lua
+++ b/lua/mason-registry/sources/file.lua
@@ -189,6 +189,11 @@ function FileRegistrySource:serialize()
}
end
+---@param other FileRegistrySource
+function FileRegistrySource:is_same_location(other)
+ return vim.fn.expand(self.spec.path) == vim.fn.expand(other.spec.path)
+end
+
function FileRegistrySource:__tostring()
return ("FileRegistrySource(path=%s)"):format(self.spec.path)
end
diff --git a/lua/mason-registry/sources/github.lua b/lua/mason-registry/sources/github.lua
index 5cc69023..597e7d84 100644
--- a/lua/mason-registry/sources/github.lua
+++ b/lua/mason-registry/sources/github.lua
@@ -171,6 +171,11 @@ function GitHubRegistrySource:serialize()
}
end
+---@param other GitHubRegistrySource
+function GitHubRegistrySource:is_same_location(other)
+ return self.spec.namespace == other.spec.namespace and self.spec.name == other.spec.name
+end
+
function GitHubRegistrySource:__tostring()
if self.spec.version then
return ("GitHubRegistrySource(repo=%s, version=%s)"):format(self.repo, self.spec.version)
diff --git a/lua/mason-registry/sources/init.lua b/lua/mason-registry/sources/init.lua
index c08a46a5..765d4904 100644
--- a/lua/mason-registry/sources/init.lua
+++ b/lua/mason-registry/sources/init.lua
@@ -1,3 +1,5 @@
+local log = require "mason-core.log"
+
---@class RegistrySource
---@field id string
---@field get_package fun(self: RegistrySource, pkg_name: string): Package?
@@ -7,6 +9,7 @@
---@field is_installed fun(self: RegistrySource): boolean
---@field install fun(self: RegistrySource): Result
---@field serialize fun(self: RegistrySource): InstallReceiptRegistry
+---@field is_same_location fun(self: RegistrySource, other: RegistrySource): boolean
---@alias RegistrySourceType '"github"' | '"lua"' | '"file"'
@@ -69,6 +72,18 @@ function LazySource:get()
return self.instance
end
+---@param other LazySource
+function LazySource:is_same_location(other)
+ if self.type == other.type then
+ return self:get():is_same_location(other:get())
+ end
+ return false
+end
+
+function LazySource:get_full_id()
+ return ("%s:%s"):format(self.type, self.id)
+end
+
function LazySource:__tostring()
return ("LazySource(type=%s, id=%s)"):format(self.type, self.id)
end
@@ -113,16 +128,40 @@ end
---@param registry string
function LazySourceCollection:append(registry)
- table.insert(self.list, parse(registry))
+ self:unique_insert(parse(registry))
return self
end
---@param registry string
function LazySourceCollection:prepend(registry)
- table.insert(self.list, 1, parse(registry))
+ self:unique_insert(parse(registry), 1)
return self
end
+---@param source LazySource
+---@param idx? integer
+function LazySourceCollection:unique_insert(source, idx)
+ idx = idx or #self.list + 1
+ if idx > 1 then
+ for i = 1, math.min(idx, #self.list) do
+ if self.list[i]:is_same_location(source) then
+ log.fmt_warn(
+ "Ignoring duplicate registry entry %s (duplicate of %s)",
+ source:get_full_id(),
+ self.list[i]:get_full_id()
+ )
+ return
+ end
+ end
+ end
+ for i = #self.list, idx, -1 do
+ if self.list[i]:is_same_location(source) then
+ table.remove(self.list, i)
+ end
+ end
+ table.insert(self.list, idx, source)
+end
+
function LazySourceCollection:is_all_installed()
for source in self:iterate { include_uninstalled = true } do
if not source:is_installed() then
@@ -171,6 +210,15 @@ function LazySourceCollection:to_list(opts)
return list
end
+---@param idx integer
+function LazySourceCollection:get(idx)
+ return self.list[idx]
+end
+
+function LazySourceCollection:size()
+ return #self.list
+end
+
function LazySourceCollection:__tostring()
return ("LazySourceCollection(list={%s})"):format(table.concat(vim.tbl_map(tostring, self.list), ", "))
end
diff --git a/lua/mason-registry/sources/lua.lua b/lua/mason-registry/sources/lua.lua
index 8b4aac33..40e728b6 100644
--- a/lua/mason-registry/sources/lua.lua
+++ b/lua/mason-registry/sources/lua.lua
@@ -88,6 +88,11 @@ function LuaRegistrySource:serialize()
}
end
+---@param other LuaRegistrySource
+function LuaRegistrySource:is_same_location(other)
+ return self.id == other.id
+end
+
function LuaRegistrySource:__tostring()
return ("LuaRegistrySource(mod=%s)"):format(self.spec.mod)
end
diff --git a/tests/mason-registry/sources/collection_spec.lua b/tests/mason-registry/sources/collection_spec.lua
new file mode 100644
index 00000000..b603c868
--- /dev/null
+++ b/tests/mason-registry/sources/collection_spec.lua
@@ -0,0 +1,21 @@
+local LazySourceCollection = require "mason-registry.sources"
+
+describe("LazySourceCollection", function()
+ it("should dedupe registries on append/prepend", function()
+ local coll = LazySourceCollection:new()
+
+ coll:append "github:mason-org/mason-registry"
+ coll:prepend "github:mason-org/mason-registry@2025-05-16"
+ coll:prepend "github:my-own/registry"
+ coll:prepend "lua:registry"
+ coll:append "lua:registry"
+ coll:append "file:~/registry"
+ coll:append "file:$HOME/registry"
+
+ assert.equals(4, coll:size())
+ assert.same("lua:registry", coll:get(1):get_full_id())
+ assert.same("github:my-own/registry", coll:get(2):get_full_id())
+ assert.same("github:mason-org/mason-registry@2025-05-16", coll:get(3):get_full_id())
+ assert.same("file:~/registry", coll:get(4):get_full_id())
+ end)
+end)