aboutsummaryrefslogtreecommitdiffstats
path: root/lua
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2025-11-22 01:36:14 +0100
committerWilliam Boman <william@redwill.se>2026-04-30 14:33:47 +0200
commit855a14a7a5697bc7743911f1edf78fb8564d58fc (patch)
tree0e376f8a9b1a7f46ce101e73d7e126b897700cee /lua
parent[WIP]: (diff)
downloadmason-855a14a7a5697bc7743911f1edf78fb8564d58fc.tar
mason-855a14a7a5697bc7743911f1edf78fb8564d58fc.tar.gz
mason-855a14a7a5697bc7743911f1edf78fb8564d58fc.tar.bz2
mason-855a14a7a5697bc7743911f1edf78fb8564d58fc.tar.lz
mason-855a14a7a5697bc7743911f1edf78fb8564d58fc.tar.xz
mason-855a14a7a5697bc7743911f1edf78fb8564d58fc.tar.zst
mason-855a14a7a5697bc7743911f1edf78fb8564d58fc.zip
[WIP]:
Diffstat (limited to 'lua')
-rw-r--r--lua/mason-core/lock/parser.lua24
-rw-r--r--lua/mason-core/lock/restore.lua148
-rw-r--r--lua/mason/ui/restore.lua1
3 files changed, 122 insertions, 51 deletions
diff --git a/lua/mason-core/lock/parser.lua b/lua/mason-core/lock/parser.lua
index 6d83a654..1b51fc2e 100644
--- a/lua/mason-core/lock/parser.lua
+++ b/lua/mason-core/lock/parser.lua
@@ -116,10 +116,32 @@ local function deserialize(file)
end
end
- return {
+ ---@type Lockfile
+ local lockfile = {
header = header,
body = body,
}
+
+ assert(lockfile.header and lockfile.header.version, "Header and version missing.")
+ assert(lockfile.header.version == "1", "Unknown lockfile version.")
+ for pkg_name, metadata in pairs(lockfile.body) do
+ assert(metadata.version, "Missing version field.")
+ assert(metadata.registry, "Missing registry field.")
+ local registry = metadata.registry
+ if registry.proto == "github" then
+ assert(registry.integrity, "integrity field missing")
+ assert(registry.name, "name field missing")
+ assert(registry.namespace, "namespace field missing")
+ elseif registry.proto == "file" then
+ assert(registry.path, "path field missing")
+ elseif registry.proto == "lua" then
+ assert(registry.mod, "mod field missing")
+ else
+ error "Unknown registry protocol."
+ end
+ end
+
+ return lockfile
end)
return parser(thread, file)
end
diff --git a/lua/mason-core/lock/restore.lua b/lua/mason-core/lock/restore.lua
index 5c4b0c95..d8ee60fe 100644
--- a/lua/mason-core/lock/restore.lua
+++ b/lua/mason-core/lock/restore.lua
@@ -1,10 +1,9 @@
local FileRegistrySource = require "mason-registry.sources.file"
local GitHubRegistrySource = require "mason-registry.sources.github"
local LuaRegistrySource = require "mason-registry.sources.lua"
+local Optional = require "mason-core.optional"
local Result = require "mason-core.result"
local _ = require "mason-core.functional"
-local a = require "mason-core.async"
-local lock = require "mason-core.lock"
local M = {}
@@ -15,54 +14,76 @@ local providers = {
local version, checksum = unpack(_.split("~", registry_info.integrity))
local cache_key = registry_info.name .. registry_info.namespace .. version
return cache(cache_key, function()
- local registry = GitHubRegistrySource:new {
+ return GitHubRegistrySource:new {
id = ("%s/%s"):format(registry_info.namespace, registry_info.name),
name = registry_info.name,
namespace = registry_info.namespace,
version = version,
}
- registry:install()
- return registry
end)
end,
---@param registry_info LockfileRegistryFile
---@return FileRegistrySource
file = function(registry_info, cache)
return cache(registry_info.path, function()
- local registry = FileRegistrySource:new {
+ return FileRegistrySource:new {
id = registry_info.path,
path = registry_info.path,
}
- registry:install()
- return registry
end)
end,
---@param registry_info LockfileRegistryLua
---@return LuaRegistrySource
lua = function(registry_info, cache)
return cache(registry_info.mod, function()
- local registry = LuaRegistrySource:new {
+ return LuaRegistrySource:new {
id = registry_info.mod,
mod = registry_info.mod,
}
- registry:install()
- return registry
end)
end,
}
-local IndexedCache = {
+---@class LockfileInstallGroup
+---@field packages table<Package, LockfilePackage>
+---@field unavailable_packages table<string, string>
+local LockfileInstallGroup = {}
+LockfileInstallGroup.__index = LockfileInstallGroup
+
+---@param packages table<Package, LockfilePackage>
+---@param unavailable_packages table<string, string>
+function LockfileInstallGroup:new(packages, unavailable_packages)
+ ---@type LockfileInstallGroup
+ local instance = {}
+ setmetatable(instance, self)
+ instance.packages = packages
+ instance.unavailable_packages = unavailable_packages
+ return instance
+end
+
+function LockfileInstallGroup:install()
+ for pkg, metadata in pairs(self.packages) do
+ print("Installing", pkg.name)
+ pkg:install({
+ no_lock = true,
+ version = metadata.version,
+ }, function(success)
+ if success then
+ print(pkg.name, "succeeded!")
+ else
+ print(pkg.name, "failed!")
+ end
+ end)
+ end
+end
+
+local RegistryCache = {
__index = function(self, root_key)
self[root_key] = {}
setmetatable(self[root_key], {
__call = function(cache, key, init)
if not cache[key] then
- local ok, registry = pcall(init)
- if ok then
- cache[key] = registry
- else
- error(registry)
- end
+ cache[key] = init()
end
return cache[key]
end,
@@ -71,46 +92,73 @@ local IndexedCache = {
end,
}
-M.restore = a.scope(function()
- local lockfile = lock.get_lockfile()
- -- TODO probably do somewhere else
- assert(lockfile, "Lockfile is nil!")
- assert(lockfile.header and lockfile.header.version == "1", "Unknown lockfile version.")
+---@class LockfileRestore
+---@field lockfile Lockfile
+---@field registry_cache table
+local LockfileRestore = {}
+LockfileRestore.__index = LockfileRestore
- local cache = setmetatable({}, IndexedCache)
+---@param lockfile Lockfile
+function LockfileRestore:new(lockfile)
+ ---@type LockfileRestore
+ local instance = {}
+ setmetatable(instance, self)
+ instance.lockfile = lockfile
+ instance.registry_cache = setmetatable({}, RegistryCache)
+ return instance
+end
- ---@param pkg_name string
- ---@param metadata LockfilePackage
- local function get_package(pkg_name, metadata)
- local registry = metadata.registry
- if registry.proto == "github" then
- return providers.github(registry, cache.github):get_package(pkg_name)
- elseif registry.proto == "lua" then
- return providers.lua(registry, cache.lua):get_package(pkg_name)
- elseif registry.proto == "file" then
- return providers.file(registry, cache.file):get_package(pkg_name)
- end
- error(("Unknown registry protocol: %s."):format(registry.proto))
+---@param registry_info LockfileRegistry
+---@return RegistrySource
+function LockfileRestore:get_registry(registry_info)
+ if registry_info.proto == "github" then
+ return providers.github(registry_info, self.registry_cache.github)
+ elseif registry_info.proto == "lua" then
+ return providers.lua(registry_info, self.registry_cache.lua)
+ elseif registry_info.proto == "file" then
+ return providers.file(registry_info, self.registry_cache.file)
end
+end
- for pkg_name, metadata in pairs(lockfile.body) do
- ---@type Package
- local pkg = assert(get_package(pkg_name, metadata), ("Package %s not found."):format(pkg_name))
- assert(metadata.version, "Package version not specified in lockfile.")
- print("Installing", pkg_name, metadata.version)
- pkg:install({
- version = metadata.version,
- no_lock = true,
- }, function(success, err)
- print(pkg_name, "finished installing", success, err)
- end)
+---@async
+---@param pkg_name string
+---@param metadata LockfilePackage
+function LockfileRestore:get_package(pkg_name, metadata)
+ return Result.try(function(try)
+ local ephemeral_registry = self:get_registry(metadata.registry)
+ if not ephemeral_registry:is_installed() then
+ try(ephemeral_registry:install())
+ end
+ return Optional.of_nilable(ephemeral_registry:get_package(pkg_name)):ok_or "Unable to find package."
+ end)
+end
+
+---@async
+function LockfileRestore:prepare()
+ local available = {}
+ local unavailable = {}
+ for pkg_name, metadata in pairs(self.lockfile.body) do
+ self:get_package(pkg_name, metadata)
+ :on_success(function(pkg)
+ available[pkg] = metadata
+ end)
+ :on_failure(function(err)
+ unavailable[pkg_name] = err
+ end)
end
+ return LockfileInstallGroup:new(available, unavailable)
+end
- for _, registry in pairs(cache.github) do
+function LockfileRestore:cleanup()
+ for _, registry in pairs(self.registry_cache.github) do
registry:uninstall()
end
-end)
+end
-M.restore()
+require("mason-core.async").run_blocking(function()
+ local restore = LockfileRestore:new(require("mason-core.lock").get_lockfile())
+ restore:prepare():install()
+ -- restore:cleanup()
+end)
return M
diff --git a/lua/mason/ui/restore.lua b/lua/mason/ui/restore.lua
new file mode 100644
index 00000000..2e3f13af
--- /dev/null
+++ b/lua/mason/ui/restore.lua
@@ -0,0 +1 @@
+local restore = require("mason-core.lock.restore")