diff options
| author | William Boman <william@redwill.se> | 2022-10-30 17:43:46 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-10-30 17:43:46 +0100 |
| commit | 37c745fa73b983c86904132efb30ef2a4a76df5e (patch) | |
| tree | c55fe52b7c5c20ed4fdbb3ee073519fd0ccbe6b2 /lua/mason-core | |
| parent | chore: update generated code (#608) (diff) | |
| download | mason-37c745fa73b983c86904132efb30ef2a4a76df5e.tar mason-37c745fa73b983c86904132efb30ef2a4a76df5e.tar.gz mason-37c745fa73b983c86904132efb30ef2a4a76df5e.tar.bz2 mason-37c745fa73b983c86904132efb30ef2a4a76df5e.tar.lz mason-37c745fa73b983c86904132efb30ef2a4a76df5e.tar.xz mason-37c745fa73b983c86904132efb30ef2a4a76df5e.tar.zst mason-37c745fa73b983c86904132efb30ef2a4a76df5e.zip | |
feat: add provider interface (#601)
Diffstat (limited to 'lua/mason-core')
| -rw-r--r-- | lua/mason-core/functional/function.lua | 5 | ||||
| -rw-r--r-- | lua/mason-core/functional/init.lua | 3 | ||||
| -rw-r--r-- | lua/mason-core/functional/list.lua | 7 | ||||
| -rw-r--r-- | lua/mason-core/functional/string.lua | 4 | ||||
| -rw-r--r-- | lua/mason-core/managers/github/client.lua | 13 | ||||
| -rw-r--r-- | lua/mason-core/managers/npm/init.lua | 4 | ||||
| -rw-r--r-- | lua/mason-core/managers/pip3/init.lua | 48 | ||||
| -rw-r--r-- | lua/mason-core/optional.lua | 8 | ||||
| -rw-r--r-- | lua/mason-core/providers/init.lua | 77 | ||||
| -rw-r--r-- | lua/mason-core/spawn.lua | 2 |
10 files changed, 128 insertions, 43 deletions
diff --git a/lua/mason-core/functional/function.lua b/lua/mason-core/functional/function.lua index c6d460a5..f1475229 100644 --- a/lua/mason-core/functional/function.lua +++ b/lua/mason-core/functional/function.lua @@ -89,4 +89,9 @@ _.lazy = function(fn) end end +_.tap = _.curryN(function(fn, value) + fn(value) + return value +end, 2) + return _ diff --git a/lua/mason-core/functional/init.lua b/lua/mason-core/functional/init.lua index ed502a4b..04ef1534 100644 --- a/lua/mason-core/functional/init.lua +++ b/lua/mason-core/functional/init.lua @@ -27,6 +27,7 @@ _.T = fun.T _.F = fun.F _.memoize = fun.memoize _.lazy = fun.lazy +_.tap = fun.tap ---@module "mason-core.functional.list" local list = lazy_require "mason-core.functional.list" @@ -45,6 +46,7 @@ _.prepend = list.prepend _.zip_table = list.zip_table _.nth = list.nth _.head = list.head +_.last = list.last _.length = list.length _.flatten = list.flatten _.sort_by = list.sort_by @@ -80,6 +82,7 @@ _.dec = number.dec ---@module "mason-core.functional.string" local string = lazy_require "mason-core.functional.string" _.matches = string.matches +_.match = string.match _.format = string.format _.split = string.split _.gsub = string.gsub diff --git a/lua/mason-core/functional/list.lua b/lua/mason-core/functional/list.lua index 31b631b8..2a5378fe 100644 --- a/lua/mason-core/functional/list.lua +++ b/lua/mason-core/functional/list.lua @@ -148,6 +148,13 @@ end, 2) _.head = _.nth(1) +---@generic T +---@param list T[] +---@return T? +_.last = function(list) + return list[#list] +end + ---@param value string|any[] _.length = function(value) return #value diff --git a/lua/mason-core/functional/string.lua b/lua/mason-core/functional/string.lua index 7726c8e1..9b7da979 100644 --- a/lua/mason-core/functional/string.lua +++ b/lua/mason-core/functional/string.lua @@ -8,6 +8,10 @@ _.matches = fun.curryN(function(pattern, str) return str:match(pattern) ~= nil end, 2) +_.match = fun.curryN(function(pattern, str) + return { str:match(pattern) } +end, 2) + ---@param template string ---@param str string _.format = fun.curryN(function(template, str) diff --git a/lua/mason-core/managers/github/client.lua b/lua/mason-core/managers/github/client.lua index 3ef307c1..699e3fa4 100644 --- a/lua/mason-core/managers/github/client.lua +++ b/lua/mason-core/managers/github/client.lua @@ -2,13 +2,10 @@ local _ = require "mason-core.functional" local log = require "mason-core.log" local fetch = require "mason-core.fetch" local spawn = require "mason-core.spawn" -local api = require "mason-registry.api" +local providers = require "mason-core.providers" local M = {} ----@alias GitHubReleaseAsset {url: string, id: integer, name: string, browser_download_url: string, created_at: string, updated_at: string, size: integer, download_count: integer} ----@alias GitHubRelease {tag_name: string, prerelease: boolean, draft: boolean, assets:GitHubReleaseAsset[]} ----@alias GitHubTag {name: string} ---@alias GitHubCommit {sha: string} local stringify_params = _.compose(_.join "&", _.map(_.join "="), _.sort_by(_.head), _.to_pairs) @@ -66,11 +63,7 @@ end ---@return Result # Result<GitHubRelease> function M.fetch_latest_release(repo, opts) opts = opts or { include_prerelease = false } - return api.repo.releases.latest({ repo = repo }, { - params = { - include_prerelease = opts.include_prerelease and "true" or "false", - }, - }) + return providers.github.get_latest_release(repo, { include_prerelease = opts.include_prerelease }) end ---@async @@ -87,7 +80,7 @@ end ---@param repo string The GitHub repo ("username/repo"). ---@return Result # Result<string> The latest tag name. function M.fetch_latest_tag(repo) - return api.repo.tags.latest({ repo = repo }):map(_.prop "tag") + return providers.github.get_latest_tag(repo):map(_.prop "tag") end ---@async diff --git a/lua/mason-core/managers/npm/init.lua b/lua/mason-core/managers/npm/init.lua index 61ee4042..96571420 100644 --- a/lua/mason-core/managers/npm/init.lua +++ b/lua/mason-core/managers/npm/init.lua @@ -4,7 +4,7 @@ local Result = require "mason-core.result" local path = require "mason-core.path" local _ = require "mason-core.functional" local platform = require "mason-core.platform" -local api = require "mason-registry.api" +local providers = require "mason-core.providers" local list_copy = _.list_copy @@ -112,7 +112,7 @@ function M.check_outdated_primary_package(receipt, install_dir) local primary_package = receipt.primary_source.package return M.get_installed_primary_package_version(receipt, install_dir) :and_then(function(installed_version) - return api.npm.versions.latest({ package = primary_package }):map(function(response) + return providers.npm.get_latest_version(primary_package):map(function(response) return { installed = installed_version, latest = response.version, diff --git a/lua/mason-core/managers/pip3/init.lua b/lua/mason-core/managers/pip3/init.lua index 4581bc0b..67f70a89 100644 --- a/lua/mason-core/managers/pip3/init.lua +++ b/lua/mason-core/managers/pip3/init.lua @@ -7,6 +7,7 @@ local Optional = require "mason-core.optional" local installer = require "mason-core.installer" local Result = require "mason-core.result" local spawn = require "mason-core.spawn" +local providers = require "mason-core.providers" local VENV_DIR = "venv" @@ -103,36 +104,27 @@ function M.check_outdated_primary_package(receipt, install_dir) return Result.failure "Receipt does not have a primary source of type pip3" end local normalized_package = M.normalize_package(receipt.primary_source.package) - return spawn - .python({ - "-m", - "pip", - "list", - "--outdated", - "--format=json", - cwd = install_dir, - with_paths = { M.venv_path(install_dir) }, - }) - :map_catching(function(result) - ---@alias PipOutdatedPackage {name: string, version: string, latest_version: string} - ---@type PipOutdatedPackage[] - local packages = vim.json.decode(result.stdout) - - local outdated_primary_package = _.find_first(function(outdated_package) - return outdated_package.name == normalized_package - and outdated_package.version ~= outdated_package.latest_version - end, packages) - - return Optional.of_nilable(outdated_primary_package) - :map(function(pkg) - return { + return M.get_installed_primary_package_version(receipt, install_dir):and_then(function(installed_version) + return providers.pypi + .get_latest_version(normalized_package) + :map(function(latest) + return { + current = installed_version, + latest = latest.version, + } + end) + :and_then(function(versions) + if versions.current ~= versions.latest then + return Result.success { name = normalized_package, - current_version = assert(pkg.version, "missing current pip3 package version"), - latest_version = assert(pkg.latest_version, "missing latest pip3 package version"), + current_version = versions.current, + latest_version = versions.latest, } - end) - :or_else_throw "Primary package is not outdated." - end) + else + return Result.failure "Primary package is not outdated." + end + end) + end) end ---@async diff --git a/lua/mason-core/optional.lua b/lua/mason-core/optional.lua index 6eb0719e..cc40da77 100644 --- a/lua/mason-core/optional.lua +++ b/lua/mason-core/optional.lua @@ -105,13 +105,17 @@ function Optional:is_present() return self._value ~= nil end ----@param err fun(): any +---@param err (fun(): any)|string function Optional:ok_or(err) local Result = require "mason-core.result" if self:is_present() then return Result.success(self:get()) else - return Result.failure(err()) + if type(err) == "string" then + return Result.failure(err) + else + return Result.failure(err()) + end end end diff --git a/lua/mason-core/providers/init.lua b/lua/mason-core/providers/init.lua new file mode 100644 index 00000000..76bd431b --- /dev/null +++ b/lua/mason-core/providers/init.lua @@ -0,0 +1,77 @@ +local settings = require "mason.settings" +local log = require "mason-core.log" +local Result = require "mason-core.result" + +---@alias GitHubReleaseAsset {url: string, id: integer, name: string, browser_download_url: string, created_at: string, updated_at: string, size: integer, download_count: integer} +---@alias GitHubRelease { tag_name: string, prerelease: boolean, draft: boolean, assets:GitHubReleaseAsset[] } +---@alias GitHubTag { name: string } + +---@class GitHubProvider +---@field get_latest_release? async fun(repo: string, opts?: { include_prerelease?: boolean }): Result # Result<GitHubRelease> +---@field get_all_release_versions? async fun(repo: string): Result # Result<string[]> +---@field get_latest_tag? async fun(repo: string): Result # Result<GitHubTag> +---@field get_all_tags? async fun(repo: string): Result # Result<string[]> + +---@alias NpmPackage { name: string, version: string } + +---@class NpmProvider +---@field get_latest_version? async fun(pkg: string): Result # Result<NpmPackage> +---@field get_all_versions? async fun(pkg: string): Result # Result<string[]> + +---@alias PyPiPackage { name: string, version: string } + +---@class PyPiProvider +---@field get_latest_version? async fun(pkg: string): Result # Result<PyPiPackage> +---@field get_all_versions? async fun(pkg: string): Result # Result<string[]> # Sorting should not be relied upon due to "proprietary" sorting algo in pip that is difficult to replicate in mason-registry-api. + +---@class Provider +---@field github? GitHubProvider +---@field npm? NpmProvider +---@field pypi? PyPiProvider + +local function service_mt(service) + return setmetatable({}, { + __index = function(_, method) + return function(...) + if #settings.current.providers < 1 then + log.error "No providers configured." + return Result.failure "1 or more providers are required." + end + for _, provider_module in ipairs(settings.current.providers) do + local ok, provider = pcall(require, provider_module) + if ok and provider then + local impl = provider[service] and provider[service][method] + if impl then + ---@type boolean, Result + local ok, result = pcall(impl, ...) + if ok and result:is_success() then + return result + else + if getmetatable(result) == Result then + log.fmt_error("Provider %s %s failed: %s", service, method, result:err_or_nil()) + else + log.fmt_error("Provider %s %s errored: %s", service, method, result) + end + end + end + else + log.fmt_error("Unable to find provider %s is not registered. %s", provider_module, provider) + end + end + local err = ("No provider implementation found for %s.%s"):format(service, method) + log.error(err) + return Result.failure(err) + end + end, + }) +end + +---@type Provider +local providers = setmetatable({}, { + __index = function(tbl, service) + tbl[service] = service_mt(service) + return tbl[service] + end, +}) + +return providers diff --git a/lua/mason-core/spawn.lua b/lua/mason-core/spawn.lua index fd01c97a..814ef8f7 100644 --- a/lua/mason-core/spawn.lua +++ b/lua/mason-core/spawn.lua @@ -5,7 +5,7 @@ local process = require "mason-core.process" local platform = require "mason-core.platform" local log = require "mason-core.log" ----@alias JobSpawn table<string, async fun(opts: JobSpawnOpts): Result> +---@alias JobSpawn table<string, async fun(opts: SpawnArgs): Result> ---@type JobSpawn local spawn = { _aliases = { |
