aboutsummaryrefslogtreecommitdiffstats
path: root/lua/mason-core/package/init.lua
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2023-03-12 08:21:15 +0100
committerGitHub <noreply@github.com>2023-03-12 08:21:15 +0100
commita01d02ad7f680aec98a1e2ec35b04cedd307cfa8 (patch)
tree1a09e274a1f2a4da85b911abcbb182a211035501 /lua/mason-core/package/init.lua
parentfeat(golangci-lint): support linux_arm64 (#1089) (diff)
downloadmason-a01d02ad7f680aec98a1e2ec35b04cedd307cfa8.tar
mason-a01d02ad7f680aec98a1e2ec35b04cedd307cfa8.tar.gz
mason-a01d02ad7f680aec98a1e2ec35b04cedd307cfa8.tar.bz2
mason-a01d02ad7f680aec98a1e2ec35b04cedd307cfa8.tar.lz
mason-a01d02ad7f680aec98a1e2ec35b04cedd307cfa8.tar.xz
mason-a01d02ad7f680aec98a1e2ec35b04cedd307cfa8.tar.zst
mason-a01d02ad7f680aec98a1e2ec35b04cedd307cfa8.zip
feat: add github registry source capabilities (#1091)
Diffstat (limited to 'lua/mason-core/package/init.lua')
-rw-r--r--lua/mason-core/package/init.lua132
1 files changed, 112 insertions, 20 deletions
diff --git a/lua/mason-core/package/init.lua b/lua/mason-core/package/init.lua
index 88e89c41..16250ead 100644
--- a/lua/mason-core/package/init.lua
+++ b/lua/mason-core/package/init.lua
@@ -6,10 +6,16 @@ local log = require "mason-core.log"
local EventEmitter = require "mason-core.EventEmitter"
local fs = require "mason-core.fs"
local path = require "mason-core.path"
+local Result = require "mason-core.result"
+local Purl = require "mason-core.purl"
+
+local is_not_nil = _.complement(_.is_nil)
+local is_registry_schema_id = _.matches "^registry%+v[1-9]+$"
+local is_registry_spec = _.prop_satisfies(_.all_pass { is_not_nil, is_registry_schema_id }, "schema")
---@class Package : EventEmitter
---@field name string
----@field spec PackageSpec
+---@field spec RegistryPackageSpec | PackageSpec
---@field private handle InstallHandle The currently associated handle.
local Package = setmetatable({}, { __index = EventEmitter })
@@ -50,16 +56,52 @@ local PackageMt = { __index = Package }
---@field languages PackageLanguage[]
---@field install async fun(ctx: InstallContext)
----@param spec PackageSpec
+---@class RegistryPackageSourceVersionOverride : RegistryPackageSource
+---@field constraint string
+
+---@class RegistryPackageSource
+---@field id string PURL-compliant identifier.
+---@field version_overrides? RegistryPackageSourceVersionOverride[]
+
+---@class RegistryPackageSpec
+---@field schema '"registry+v1"'
+---@field name string
+---@field description string
+---@field homepage string
+---@field licenses string[]
+---@field languages string[]
+---@field categories string[]
+---@field source RegistryPackageSource
+---@field bin table<string, string>?
+---@field share table<string, string>?
+---@field opt table<string, string>?
+
+---@param spec PackageSpec | RegistryPackageSpec
function Package.new(spec)
- vim.validate {
- name = { spec.name, "s" },
- desc = { spec.desc, "s" },
- homepage = { spec.homepage, "s" },
- categories = { spec.categories, "t" },
- languages = { spec.languages, "t" },
- install = { spec.install, "f" },
- }
+ if is_registry_spec(spec) then
+ vim.validate {
+ name = { spec.name, "s" },
+ description = { spec.description, "s" },
+ homepage = { spec.homepage, "s" },
+ licenses = { spec.licenses, "t" },
+ categories = { spec.categories, "t" },
+ languages = { spec.languages, "t" },
+ source = { spec.source, "t" },
+ bin = { spec.bin, { "t", "nil" } },
+ share = { spec.share, { "t", "nil" } },
+ }
+ -- XXX: this is for compatibilty with the PackageSpec structure
+ spec.desc = spec.description
+ else
+ vim.validate {
+ name = { spec.name, "s" },
+ desc = { spec.desc, "s" },
+ homepage = { spec.homepage, "s" },
+ categories = { spec.categories, "t" },
+ languages = { spec.languages, "t" },
+ install = { spec.install, "f" },
+ }
+ end
return EventEmitter.init(setmetatable({
name = spec.name, -- for convenient access
@@ -190,20 +232,65 @@ end
---@param callback fun(success: boolean, version_or_err: string)
function Package:get_installed_version(callback)
- a.run(function()
- local receipt = self:get_receipt():or_else_throw "Unable to get receipt."
- local version_checks = require "mason-core.package.version-check"
- return version_checks.get_installed_version(receipt, self:get_install_path()):get_or_throw()
- end, callback)
+ self:get_receipt()
+ :if_present(
+ ---@param receipt InstallReceipt
+ function(receipt)
+ if is_registry_schema_id(receipt.primary_source.type) then
+ local resolve = _.curryN(callback, 2)
+ Purl.parse(receipt.primary_source.id)
+ :map(_.prop "version")
+ :on_success(resolve(true))
+ :on_failure(resolve(false))
+ else
+ a.run(function()
+ local version_checks = require "mason-core.package.version-check"
+ return version_checks.get_installed_version(receipt, self:get_install_path()):get_or_throw()
+ end, callback)
+ end
+ end
+ )
+ :if_not_present(function()
+ callback(false, "Unable to get receipt.")
+ end)
end
---@param callback fun(success: boolean, result_or_err: NewPackageVersion)
function Package:check_new_version(callback)
- a.run(function()
- local receipt = self:get_receipt():or_else_throw "Unable to get receipt."
- local version_checks = require "mason-core.package.version-check"
- return version_checks.get_new_version(receipt, self:get_install_path()):get_or_throw()
- end, callback)
+ if self:is_registry_spec() then
+ self:get_installed_version(function(success, installed_version)
+ if not success then
+ return callback(false, installed_version)
+ end
+ local resolve = _.curryN(callback, 2)
+ Result.try(function(try)
+ -- This is a bit goofy, but it's done to verify that a new version is supported by the
+ -- current platform (parse fails if it's not). We don't want to surface new versions that
+ -- are unsupported.
+ try(require("mason-core.installer.registry").parse(self.spec, {}))
+
+ ---@type Purl
+ local purl = try(Purl.parse(self.spec.source.id))
+ if purl.version and installed_version ~= purl.version then
+ return {
+ name = purl.name,
+ current_version = installed_version,
+ latest_version = purl.version,
+ }
+ else
+ return Result.failure "Package is not outdated."
+ end
+ end)
+ :on_success(resolve(true))
+ :on_failure(resolve(false))
+ end)
+ else
+ a.run(function()
+ local receipt = self:get_receipt():or_else_throw "Unable to get receipt."
+ local version_checks = require "mason-core.package.version-check"
+ return version_checks.get_new_version(receipt, self:get_install_path()):get_or_throw()
+ end, callback)
+ end
end
function Package:get_lsp_settings_schema()
@@ -214,6 +301,11 @@ function Package:get_lsp_settings_schema()
return Optional.of(schema)
end
+---@return boolean
+function Package:is_registry_spec()
+ return is_registry_spec(self.spec)
+end
+
function PackageMt.__tostring(self)
return ("Package(name=%s)"):format(self.name)
end