aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lua/mason-core/fetch.lua2
-rw-r--r--lua/mason-core/installer/context.lua9
-rw-r--r--lua/mason-core/installer/managers/common.lua2
-rw-r--r--lua/mason-core/installer/managers/powershell.lua (renamed from lua/mason-core/managers/powershell/init.lua)0
-rw-r--r--lua/mason-core/installer/managers/pypi.lua8
-rw-r--r--lua/mason-core/installer/managers/std.lua2
-rw-r--r--lua/mason-core/managers/cargo/client.lua18
-rw-r--r--lua/mason-core/managers/cargo/init.lua199
-rw-r--r--lua/mason-core/managers/composer/init.lua127
-rw-r--r--lua/mason-core/managers/dotnet/init.lua56
-rw-r--r--lua/mason-core/managers/gem/init.lua162
-rw-r--r--lua/mason-core/managers/git/init.lua76
-rw-r--r--lua/mason-core/managers/github/client.lua84
-rw-r--r--lua/mason-core/managers/github/init.lua208
-rw-r--r--lua/mason-core/managers/go/init.lua167
-rw-r--r--lua/mason-core/managers/luarocks/init.lua137
-rw-r--r--lua/mason-core/managers/npm/init.lua136
-rw-r--r--lua/mason-core/managers/opam/init.lua62
-rw-r--r--lua/mason-core/managers/pip3/init.lua173
-rw-r--r--lua/mason-core/managers/std/init.lua196
-rw-r--r--tests/mason-core/installer/context_spec.lua8
-rw-r--r--tests/mason-core/installer/managers/powershell_spec.lua (renamed from tests/mason-core/managers/powershell_spec.lua)4
-rw-r--r--tests/mason-core/managers/cargo_spec.lua350
-rw-r--r--tests/mason-core/managers/composer_spec.lua173
-rw-r--r--tests/mason-core/managers/dotnet_spec.lua38
-rw-r--r--tests/mason-core/managers/gem_spec.lua190
-rw-r--r--tests/mason-core/managers/git_spec.lua181
-rw-r--r--tests/mason-core/managers/github_client_spec.lua23
-rw-r--r--tests/mason-core/managers/github_spec.lua103
-rw-r--r--tests/mason-core/managers/go_spec.lua171
-rw-r--r--tests/mason-core/managers/luarocks_spec.lua139
-rw-r--r--tests/mason-core/managers/npm_spec.lua206
-rw-r--r--tests/mason-core/managers/opam_spec.lua57
-rw-r--r--tests/mason-core/managers/pip3_spec.lua284
34 files changed, 20 insertions, 3731 deletions
diff --git a/lua/mason-core/fetch.lua b/lua/mason-core/fetch.lua
index c8a8591c..26ddb0f7 100644
--- a/lua/mason-core/fetch.lua
+++ b/lua/mason-core/fetch.lua
@@ -4,7 +4,7 @@ local a = require "mason-core.async"
local async_uv = require "mason-core.async.uv"
local log = require "mason-core.log"
local platform = require "mason-core.platform"
-local powershell = require "mason-core.managers.powershell"
+local powershell = require "mason-core.installer.managers.powershell"
local spawn = require "mason-core.spawn"
local version = require "mason.version"
diff --git a/lua/mason-core/installer/context.lua b/lua/mason-core/installer/context.lua
index 7637209f..21c9c26f 100644
--- a/lua/mason-core/installer/context.lua
+++ b/lua/mason-core/installer/context.lua
@@ -303,10 +303,10 @@ end
---@param new_executable_rel_path string Relative path to the executable file to create.
---@param module string The python module to call.
function InstallContext:write_pyvenv_exec_wrapper(new_executable_rel_path, module)
- local pip3 = require "mason-core.managers.pip3"
+ local pypi = require "mason-core.installer.managers.pypi"
local module_exists, module_err = pcall(function()
local result =
- self.spawn.python { "-c", ("import %s"):format(module), with_paths = { pip3.venv_path(self.cwd:get()) } }
+ self.spawn.python { "-c", ("import %s"):format(module), with_paths = { pypi.venv_path(self.cwd:get()) } }
if not self.spawn.strict_mode then
result:get_or_throw()
end
@@ -319,7 +319,7 @@ function InstallContext:write_pyvenv_exec_wrapper(new_executable_rel_path, modul
new_executable_rel_path,
("%q -m %s"):format(
path.concat {
- pip3.venv_path(self.package:get_install_path()),
+ pypi.venv_path(self.package:get_install_path()),
"python",
},
module
@@ -367,14 +367,13 @@ function InstallContext:write_shell_exec_wrapper(new_executable_rel_path, comman
end
return platform.when {
unix = function()
- local std = require "mason-core.managers.std"
local formatted_envs = _.map(function(pair)
local var, value = pair[1], pair[2]
return ("export %s=%q"):format(var, value)
end, _.to_pairs(env or {}))
self.fs:write_file(new_executable_rel_path, BASH_TEMPLATE:format(_.join("\n", formatted_envs), command))
- std.chmod("+x", { new_executable_rel_path })
+ self.fs:chmod_exec(new_executable_rel_path)
return new_executable_rel_path
end,
win = function()
diff --git a/lua/mason-core/installer/managers/common.lua b/lua/mason-core/installer/managers/common.lua
index c730a3aa..c13d3bff 100644
--- a/lua/mason-core/installer/managers/common.lua
+++ b/lua/mason-core/installer/managers/common.lua
@@ -5,7 +5,7 @@ local async_uv = require "mason-core.async.uv"
local installer = require "mason-core.installer"
local log = require "mason-core.log"
local platform = require "mason-core.platform"
-local powershell = require "mason-core.managers.powershell"
+local powershell = require "mason-core.installer.managers.powershell"
local std = require "mason-core.installer.managers.std"
local M = {}
diff --git a/lua/mason-core/managers/powershell/init.lua b/lua/mason-core/installer/managers/powershell.lua
index 0e7f4145..0e7f4145 100644
--- a/lua/mason-core/managers/powershell/init.lua
+++ b/lua/mason-core/installer/managers/powershell.lua
diff --git a/lua/mason-core/installer/managers/pypi.lua b/lua/mason-core/installer/managers/pypi.lua
index f60a8ede..d5368bc8 100644
--- a/lua/mason-core/installer/managers/pypi.lua
+++ b/lua/mason-core/installer/managers/pypi.lua
@@ -15,6 +15,14 @@ local M = {}
local VENV_DIR = "venv"
+function M.venv_path(dir)
+ return path.concat {
+ dir,
+ VENV_DIR,
+ platform.is.win and "Scripts" or "bin",
+ }
+end
+
---@async
---@param candidates string[]
local function resolve_python3(candidates)
diff --git a/lua/mason-core/installer/managers/std.lua b/lua/mason-core/installer/managers/std.lua
index 6e1a0d9e..b4eb11ab 100644
--- a/lua/mason-core/installer/managers/std.lua
+++ b/lua/mason-core/installer/managers/std.lua
@@ -6,7 +6,7 @@ local installer = require "mason-core.installer"
local log = require "mason-core.log"
local path = require "mason-core.path"
local platform = require "mason-core.platform"
-local powershell = require "mason-core.managers.powershell"
+local powershell = require "mason-core.installer.managers.powershell"
local M = {}
diff --git a/lua/mason-core/managers/cargo/client.lua b/lua/mason-core/managers/cargo/client.lua
deleted file mode 100644
index 82dc85aa..00000000
--- a/lua/mason-core/managers/cargo/client.lua
+++ /dev/null
@@ -1,18 +0,0 @@
-local fetch = require "mason-core.fetch"
-
-local M = {}
-
----@alias CrateResponse {crate: {id: string, max_stable_version: string, max_version: string, newest_version: string}}
-
----@async
----@param crate string
----@return Result # Result<CrateResponse>
-function M.fetch_crate(crate)
- return fetch(("https://crates.io/api/v1/crates/%s"):format(crate), {
- headers = {
- Accept = "application/json",
- },
- }):map_catching(vim.json.decode)
-end
-
-return M
diff --git a/lua/mason-core/managers/cargo/init.lua b/lua/mason-core/managers/cargo/init.lua
deleted file mode 100644
index 49a5841a..00000000
--- a/lua/mason-core/managers/cargo/init.lua
+++ /dev/null
@@ -1,199 +0,0 @@
-local Optional = require "mason-core.optional"
-local _ = require "mason-core.functional"
-local a = require "mason-core.async"
-local client = require "mason-core.managers.cargo.client"
-local github = require "mason-core.managers.github"
-local github_client = require "mason-core.managers.github.client"
-local installer = require "mason-core.installer"
-local path = require "mason-core.path"
-local platform = require "mason-core.platform"
-local spawn = require "mason-core.spawn"
-
-local get_bin_path = _.compose(path.concat, function(executable)
- return _.append(executable, { "bin" })
-end, _.if_else(_.always(platform.is.win), _.format "%s.exe", _.identity))
-
----@param crate string
-local function with_receipt(crate)
- return function()
- local ctx = installer.context()
- ctx.receipt:with_primary_source(ctx.receipt.cargo(crate))
- end
-end
-
-local M = {}
-
----@async
----@param crate string The crate to install.
----@param opts { git: { url: string, tag: boolean? }, features: string?, bin: string[]? }?
-function M.crate(crate, opts)
- return function()
- if opts and opts.git and opts.git.tag then
- local ctx = installer.context()
- local repo = assert(opts.git.url:match "^https://github%.com/(.+)$", "git url needs to be github.com")
- local source = github.tag { repo = repo }
- source.with_receipt()
- ctx.requested_version = Optional.of(source.tag)
- M.install(crate, opts)
- else
- M.install(crate, opts).with_receipt()
- end
- end
-end
-
----@async
----@param crate string The crate to install.
----@param opts { git: { url: string, tag: boolean? }, features: string?, bin: string[]? }?
-function M.install(crate, opts)
- local ctx = installer.context()
- opts = opts or {}
-
- local version
-
- if opts.git then
- if opts.git.tag then
- assert(ctx.requested_version:is_present(), "version is required when installing tagged git crate.")
- end
- version = ctx.requested_version
- :map(function(version)
- if opts.git.tag then
- return { "--tag", version }
- else
- return { "--rev", version }
- end
- end)
- :or_else(vim.NIL)
- else
- version = ctx.requested_version
- :map(function(version)
- return { "--version", version }
- end)
- :or_else(vim.NIL)
- end
-
- ctx.spawn.cargo {
- "install",
- "--root",
- ".",
- "--locked",
- version,
- opts.git and { "--git", opts.git.url } or vim.NIL,
- opts.features and { "--features", opts.features } or vim.NIL,
- crate,
- }
-
- if opts.bin then
- _.each(function(bin)
- ctx:link_bin(bin, get_bin_path(bin))
- end, opts.bin)
- end
-
- return {
- with_receipt = with_receipt(crate),
- }
-end
-
----@alias InstalledCrate { name: string, version: string, github_ref: { owner: string, repo: string, ref: string }? }
-
----@param line string
----@return InstalledCrate? crate
-local function parse_installed_crate(line)
- local name, version, context = line:match "^(.+)%s+v([^%s:]+) ?(.*):$"
- if context then
- local owner, repo, ref = context:match "^%(https://github%.com/(.+)/([^?]+).*#(.+)%)$"
- if ref then
- return { name = name, version = ref, github_ref = { owner = owner, repo = repo, ref = ref } }
- end
- end
- if name and version then
- return { name = name, version = version }
- end
-end
-
----@param output string The `cargo install --list` output.
----@return table<string, InstalledCrate> # Key is the crate name, value is its version.
-function M.parse_installed_crates(output)
- local installed_crates = {}
- for _, line in ipairs(vim.split(output, "\n")) do
- local installed_crate = parse_installed_crate(line)
- if installed_crate then
- installed_crates[installed_crate.name] = installed_crate
- end
- end
- return installed_crates
-end
-
----@async
----@param install_dir string
----@return Result # Result<table<string, InstalledCrate>>
-local function get_installed_crates(install_dir)
- return spawn
- .cargo({
- "install",
- "--list",
- "--root",
- ".",
- cwd = install_dir,
- })
- :map_catching(function(result)
- return M.parse_installed_crates(result.stdout)
- end)
-end
-
----@async
----@param receipt InstallReceipt<InstallReceiptPackageSource>
----@param install_dir string
-function M.check_outdated_primary_package(receipt, install_dir)
- a.scheduler()
- local crate_name = vim.fn.fnamemodify(receipt.primary_source.package, ":t")
- return get_installed_crates(install_dir)
- :ok()
- :map(_.prop(crate_name))
- :map(
- ---@param installed_crate InstalledCrate
- function(installed_crate)
- if installed_crate.github_ref then
- ---@type GitHubCommit
- local latest_commit = github_client
- .fetch_commits(
- ("%s/%s"):format(installed_crate.github_ref.owner, installed_crate.github_ref.repo),
- { page = 1, per_page = 1 }
- )
- :get_or_throw("Failed to fetch latest commits.")[1]
- if not vim.startswith(latest_commit.sha, installed_crate.github_ref.ref) then
- return {
- name = receipt.primary_source.package,
- current_version = installed_crate.github_ref.ref,
- latest_version = latest_commit.sha,
- }
- end
- else
- ---@type CrateResponse
- local crate_response = client.fetch_crate(crate_name):get_or_throw()
- if installed_crate.version ~= crate_response.crate.max_stable_version then
- return {
- name = receipt.primary_source.package,
- current_version = installed_crate.version,
- latest_version = crate_response.crate.max_stable_version,
- }
- end
- end
- end
- )
- :ok_or(_.always "Primary package is not outdated.")
-end
-
----@async
----@param receipt InstallReceipt<InstallReceiptPackageSource>
----@param install_dir string
-function M.get_installed_primary_package_version(receipt, install_dir)
- a.scheduler()
- local crate_name = vim.fn.fnamemodify(receipt.primary_source.package, ":t")
- return get_installed_crates(install_dir)
- :ok()
- :map(_.prop(crate_name))
- :map(_.prop "version")
- :ok_or(_.always "Failed to find cargo package version.")
-end
-
-return M
diff --git a/lua/mason-core/managers/composer/init.lua b/lua/mason-core/managers/composer/init.lua
deleted file mode 100644
index 274e2bcb..00000000
--- a/lua/mason-core/managers/composer/init.lua
+++ /dev/null
@@ -1,127 +0,0 @@
-local Optional = require "mason-core.optional"
-local Result = require "mason-core.result"
-local _ = require "mason-core.functional"
-local installer = require "mason-core.installer"
-local path = require "mason-core.path"
-local platform = require "mason-core.platform"
-local spawn = require "mason-core.spawn"
-
-local M = {}
-
-local create_bin_path = _.compose(path.concat, function(executable)
- return _.append(executable, { "vendor", "bin" })
-end, _.if_else(_.always(platform.is.win), _.format "%s.bat", _.identity))
-
----@param packages string[]
-local function with_receipt(packages)
- return function()
- local ctx = installer.context()
-
- ctx.receipt:with_primary_source(ctx.receipt.composer(packages[1]))
- for i = 2, #packages do
- ctx.receipt:with_secondary_source(ctx.receipt.composer(packages[i]))
- end
- end
-end
-
----@async
----@param packages { [number]: string, bin: string[]? } The composer packages to install. The first item in this list will be the recipient of the requested version, if set.
-function M.packages(packages)
- return function()
- return M.require(packages).with_receipt()
- end
-end
-
----@async
----@param packages { [number]: string, bin: string[]? } The composer packages to install. The first item in this list will be the recipient of the requested version, if set.
-function M.require(packages)
- local ctx = installer.context()
- local pkgs = _.list_copy(packages)
-
- if not ctx.fs:file_exists "composer.json" then
- ctx.spawn.composer { "init", "--no-interaction", "--stability=stable" }
- end
-
- ctx.requested_version:if_present(function(version)
- pkgs[1] = ("%s:%s"):format(pkgs[1], version)
- end)
-
- ctx.spawn.composer { "require", pkgs }
-
- if packages.bin then
- _.each(function(executable)
- ctx:link_bin(executable, create_bin_path(executable))
- end, packages.bin)
- end
-
- return {
- with_receipt = with_receipt(packages),
- }
-end
-
----@async
-function M.install()
- local ctx = installer.context()
- ctx.spawn.composer {
- "install",
- "--no-interaction",
- "--no-dev",
- "--optimize-autoloader",
- "--classmap-authoritative",
- }
-end
-
----@async
----@param receipt InstallReceipt<InstallReceiptPackageSource>
----@param install_dir string
-function M.check_outdated_primary_package(receipt, install_dir)
- if receipt.primary_source.type ~= "composer" then
- return Result.failure "Receipt does not have a primary source of type composer"
- end
- return spawn
- .composer({
- "outdated",
- "--no-interaction",
- "--format=json",
- cwd = install_dir,
- })
- :map_catching(function(result)
- local outdated_packages = vim.json.decode(result.stdout)
- local outdated_package = _.find_first(function(pkg)
- return pkg.name == receipt.primary_source.package
- end, outdated_packages.installed)
- return Optional.of_nilable(outdated_package)
- :map(function(pkg)
- if pkg.version ~= pkg.latest then
- return {
- name = pkg.name,
- current_version = pkg.version,
- latest_version = pkg.latest,
- }
- end
- end)
- :or_else_throw "Primary package is not outdated."
- end)
-end
-
----@async
----@param receipt InstallReceipt<InstallReceiptPackageSource>
----@param install_dir string
-function M.get_installed_primary_package_version(receipt, install_dir)
- if receipt.primary_source.type ~= "composer" then
- return Result.failure "Receipt does not have a primary source of type composer"
- end
- return spawn
- .composer({
- "info",
- "--format=json",
- receipt.primary_source.package,
- cwd = install_dir,
- })
- :map_catching(function(result)
- local info = vim.json.decode(result.stdout)
- return info.versions[1]
- end)
-end
-
-return M
diff --git a/lua/mason-core/managers/dotnet/init.lua b/lua/mason-core/managers/dotnet/init.lua
deleted file mode 100644
index 984b2463..00000000
--- a/lua/mason-core/managers/dotnet/init.lua
+++ /dev/null
@@ -1,56 +0,0 @@
-local _ = require "mason-core.functional"
-local installer = require "mason-core.installer"
-local platform = require "mason-core.platform"
-
-local M = {}
-
-local create_bin_path = _.if_else(_.always(platform.is.win), _.format "%s.exe", _.identity)
-
----@param package string
-local function with_receipt(package)
- return function()
- local ctx = installer.context()
- ctx.receipt:with_primary_source(ctx.receipt.dotnet(package))
- end
-end
-
----@async
----@param pkg string
----@param opt { bin: string[]? }?
-function M.package(pkg, opt)
- return function()
- return M.install(pkg, opt).with_receipt()
- end
-end
-
----@async
----@param pkg string
----@param opt { bin: string[]? }?
-function M.install(pkg, opt)
- local ctx = installer.context()
- ctx.spawn.dotnet {
- "tool",
- "update",
- "--ignore-failed-sources",
- "--tool-path",
- ".",
- ctx.requested_version
- :map(function(version)
- return { "--version", version }
- end)
- :or_else(vim.NIL),
- pkg,
- }
-
- if opt and opt.bin then
- _.each(function(executable)
- ctx:link_bin(executable, create_bin_path(executable))
- end, opt.bin)
- end
-
- return {
- with_receipt = with_receipt(pkg),
- }
-end
-
-return M
diff --git a/lua/mason-core/managers/gem/init.lua b/lua/mason-core/managers/gem/init.lua
deleted file mode 100644
index dc7448bf..00000000
--- a/lua/mason-core/managers/gem/init.lua
+++ /dev/null
@@ -1,162 +0,0 @@
-local Optional = require "mason-core.optional"
-local Result = require "mason-core.result"
-local _ = require "mason-core.functional"
-local installer = require "mason-core.installer"
-local path = require "mason-core.path"
-local platform = require "mason-core.platform"
-local process = require "mason-core.process"
-local providers = require "mason-core.providers"
-local spawn = require "mason-core.spawn"
-
-local M = {}
-
----@param install_dir string
-local function env(install_dir)
- return {
- GEM_HOME = install_dir,
- GEM_PATH = install_dir,
- PATH = process.extend_path { path.concat { install_dir, "bin" } },
- }
-end
-
-local create_bin_path = _.compose(path.concat, function(executable)
- return _.append(executable, { "bin" })
-end, _.if_else(_.always(platform.is.win), _.format "%s.bat", _.identity))
-
----@async
----@param executable string
-local function link_executable(executable)
- local ctx = installer.context()
- local bin_path = create_bin_path(executable)
- if not ctx.fs:file_exists(bin_path) then
- error(("Cannot link Gem executable %q because it doesn't exist in %q."):format(executable, bin_path), 0)
- end
- ctx:link_bin(
- executable,
- ctx:write_shell_exec_wrapper(executable, path.concat { ctx.package:get_install_path(), bin_path }, {
- GEM_PATH = platform.when {
- unix = function()
- return ("%s:$GEM_PATH"):format(ctx.package:get_install_path())
- end,
- win = function()
- return ("%s;%%GEM_PATH%%"):format(ctx.package:get_install_path())
- end,
- },
- })
- )
-end
-
----@param packages string[]
-local function with_receipt(packages)
- return function()
- local ctx = installer.context()
- ctx.receipt:with_primary_source(ctx.receipt.gem(packages[1]))
- for i = 2, #packages do
- ctx.receipt:with_secondary_source(ctx.receipt.gem(packages[i]))
- end
- end
-end
-
----@async
----@param packages { [number]: string, bin: string[]? } The Gem packages to install. The first item in this list will be the recipient of the requested version, if set.
-function M.packages(packages)
- return function()
- return M.install(packages).with_receipt()
- end
-end
-
----@async
----@param packages { [number]: string, bin: string[]? } The Gem packages to install. The first item in this list will be the recipient of the requested version, if set.
-function M.install(packages)
- local ctx = installer.context()
- local pkgs = _.list_copy(packages or {})
-
- ctx.requested_version:if_present(function(version)
- pkgs[1] = ("%s:%s"):format(pkgs[1], version)
- end)
-
- ctx.spawn.gem {
- "install",
- "--no-user-install",
- "--no-format-executable",
- "--install-dir=.",
- "--bindir=bin",
- "--no-document",
- pkgs,
- env = {
- GEM_HOME = ctx.cwd:get(),
- },
- }
-
- if packages.bin then
- _.each(link_executable, packages.bin)
- end
-
- return {
- with_receipt = with_receipt(packages),
- }
-end
-
----@alias GemOutdatedPackage {name:string, current_version: string, latest_version: string}
-
----Parses the stdout of the `gem list` command into a table<package_name, version>
----@param output string
-function M.parse_gem_list_output(output)
- ---@type table<string, string>
- local gem_versions = {}
- for _, line in ipairs(vim.split(output, "\n")) do
- local gem_package, version = line:match "^(%S+) %((%S+)%)$"
- if gem_package and version then
- gem_versions[gem_package] = version
- end
- end
- return gem_versions
-end
-
----@async
----@param receipt InstallReceipt<InstallReceiptPackageSource>
----@param install_dir string
-function M.check_outdated_primary_package(receipt, install_dir)
- if receipt.primary_source.type ~= "gem" then
- return Result.failure "Receipt does not have a primary source of type gem"
- end
- return M.get_installed_primary_package_version(receipt, install_dir)
- :and_then(function(installed_version)
- return providers.rubygems.get_latest_version(receipt.primary_source.package):map(function(latest)
- return {
- installed = installed_version,
- latest = latest.version,
- }
- end)
- end)
- :and_then(function(versions)
- if versions.installed ~= versions.latest then
- return Result.success {
- name = receipt.primary_source.package,
- current_version = versions.installed,
- latest_version = versions.latest,
- }
- else
- return Result.failure "Primary package is not outdated."
- end
- end)
-end
-
----@async
----@param receipt InstallReceipt<InstallReceiptPackageSource>
----@param install_dir string
-function M.get_installed_primary_package_version(receipt, install_dir)
- return spawn
- .gem({
- "list",
- cwd = install_dir,
- env = env(install_dir),
- })
- :map_catching(function(result)
- local gems = M.parse_gem_list_output(result.stdout)
- return Optional.of_nilable(gems[receipt.primary_source.package])
- :or_else_throw "Failed to find gem package version."
- end)
-end
-
-return M
diff --git a/lua/mason-core/managers/git/init.lua b/lua/mason-core/managers/git/init.lua
deleted file mode 100644
index 099ea6c2..00000000
--- a/lua/mason-core/managers/git/init.lua
+++ /dev/null
@@ -1,76 +0,0 @@
-local Result = require "mason-core.result"
-local _ = require "mason-core.functional"
-local installer = require "mason-core.installer"
-local spawn = require "mason-core.spawn"
-
-local M = {}
-
----@param repo string
-local function with_receipt(repo)
- return function()
- local ctx = installer.context()
- ctx.receipt:with_primary_source(ctx.receipt.git_remote(repo))
- end
-end
-
----@async
----@param opts {[1]: string, recursive: boolean, version: Optional?} The first item in the table is the repository to clone.
-function M.clone(opts)
- local ctx = installer.context()
- local repo = assert(opts[1], "No git URL provided.")
- ctx.spawn.git {
- "clone",
- "--depth",
- "1",
- opts.recursive and "--recursive" or vim.NIL,
- repo,
- ".",
- }
- _.coalesce(opts.version, ctx.requested_version):if_present(function(version)
- ctx.spawn.git { "fetch", "--depth", "1", "origin", version }
- ctx.spawn.git { "checkout", "FETCH_HEAD" }
- end)
-
- return {
- with_receipt = with_receipt(repo),
- }
-end
-
----@async
----@param receipt InstallReceipt<InstallReceiptPackageSource>
----@param install_dir string
-function M.check_outdated_git_clone(receipt, install_dir)
- if receipt.primary_source.type ~= "git" then
- return Result.failure "Receipt does not have a primary source of type git"
- end
- return spawn.git({ "fetch", "origin", "HEAD", cwd = install_dir }):map_catching(function()
- local result = spawn.git({ "rev-parse", "FETCH_HEAD", "HEAD", cwd = install_dir }):get_or_throw()
- local remote_head, local_head = unpack(vim.split(result.stdout, "\n"))
- if remote_head == local_head then
- error("Git clone is up to date.", 2)
- end
- return {
- name = receipt.primary_source.remote,
- current_version = assert(local_head, "no local HEAD"),
- latest_version = assert(remote_head, "no remote HEAD"),
- }
- end)
-end
-
----@async
----@param receipt InstallReceipt<InstallReceiptPackageSource>
----@param install_dir string
-function M.get_installed_revision(receipt, install_dir)
- return spawn
- .git({
- "rev-parse",
- "--short",
- "HEAD",
- cwd = install_dir,
- })
- :map_catching(function(result)
- return assert(vim.trim(result.stdout))
- end)
-end
-
-return M
diff --git a/lua/mason-core/managers/github/client.lua b/lua/mason-core/managers/github/client.lua
deleted file mode 100644
index e8301f72..00000000
--- a/lua/mason-core/managers/github/client.lua
+++ /dev/null
@@ -1,84 +0,0 @@
-local _ = require "mason-core.functional"
-local fetch = require "mason-core.fetch"
-local spawn = require "mason-core.spawn"
-
-local M = {}
-
----@alias GitHubCommit { sha: string }
----@alias GitHubRef { ref: string }
-
-local stringify_params = _.compose(_.join "&", _.map(_.join "="), _.sort_by(_.head), _.to_pairs)
-
----@param path string
----@param opts { params: table<string, any>? }?
----@return Result # JSON decoded response.
-local function gh_api_call(path, opts)
- if opts and opts.params then
- local params = stringify_params(opts.params)
- path = ("%s?%s"):format(path, params)
- end
- return spawn
- .gh({ "api", path, env = { CLICOLOR_FORCE = 0 } })
- :map(_.prop "stdout")
- :or_else(function()
- return fetch(("https://api.github.com/%s"):format(path), {
- headers = {
- Accept = "application/vnd.github.v3+json; q=1.0, application/json; q=0.8",
- },
- })
- end)
- :map_catching(vim.json.decode)
-end
-
-M.api_call = gh_api_call
-
----@async
----@param repo string The GitHub repo ("username/repo").
----@return Result # Result<GitHubRelease>
-function M.fetch_latest_release(repo)
- local path = ("repos/%s/releases/latest"):format(repo)
- return gh_api_call(path)
-end
-
----@async
----@param repo string The GitHub repo ("username/repo").
----@return Result # Result<GitHubRelease[]>
-function M.fetch_all_releases(repo)
- local path = ("repos/%s/releases"):format(repo)
- return gh_api_call(path)
-end
-
----@async
----@param repo string The GitHub repo ("username/repo").
----@return Result # Result<GitHubRef[]>
-function M.fetch_all_tags(repo)
- local path = ("repos/%s/git/matching-refs/tags"):format(repo)
- return gh_api_call(path)
-end
-
----@async
----@param repo string The GitHub repo ("username/repo").
----@param opts { page: integer?, per_page: integer? }?
----@return Result # Result<GitHubCommit[]>
-function M.fetch_commits(repo, opts)
- local path = ("repos/%s/commits"):format(repo)
- return gh_api_call(path, {
- params = {
- page = opts and opts.page or 1,
- per_page = opts and opts.per_page or 30,
- },
- }):map_err(function()
- return ("Failed to fetch commits for GitHub repository %s."):format(repo)
- end)
-end
-
----@alias GitHubRateLimit {limit: integer, remaining: integer, reset: integer, used: integer}
----@alias GitHubRateLimitResponse {resources: { core: GitHubRateLimit }}
-
----@async
----@return Result # Result<GitHubRateLimitResponse>
-function M.fetch_rate_limit()
- return gh_api_call "rate_limit"
-end
-
-return M
diff --git a/lua/mason-core/managers/github/init.lua b/lua/mason-core/managers/github/init.lua
deleted file mode 100644
index 2d593790..00000000
--- a/lua/mason-core/managers/github/init.lua
+++ /dev/null
@@ -1,208 +0,0 @@
-local Result = require "mason-core.result"
-local _ = require "mason-core.functional"
-local installer = require "mason-core.installer"
-local platform = require "mason-core.platform"
-local providers = require "mason-core.providers"
-local settings = require "mason.settings"
-local std = require "mason-core.managers.std"
-
-local M = {}
-
----@class InstallReceiptGitHubReleaseFileSource
----@field type '"github_release_file"'
----@field repo string
----@field file string
----@field release string
-
----@param repo string
----@param asset_file string
----@param release string
-local function with_release_file_receipt(repo, asset_file, release)
- return function()
- local ctx = installer.context()
- ctx.receipt:with_primary_source {
- type = "github_release_file",
- repo = repo,
- file = asset_file,
- release = release,
- }
- end
-end
-
----@class InstallReceiptGitHubTagSource
----@field type '"github_tag"'
----@field repo string
----@field tag string
-
----@param repo string
----@param tag string
-local function with_tag_receipt(repo, tag)
- return function()
- local ctx = installer.context()
- ctx.receipt:with_primary_source {
- type = "github_tag",
- repo = repo,
- tag = tag,
- }
- end
-end
-
----@async
----@param opts {repo: string, version: Optional?}
-function M.release_version(opts)
- local ctx = installer.context()
- ---@type string
- local release = _.coalesce(opts.version, ctx.requested_version):or_else_get(function()
- return providers.github
- .get_latest_release(opts.repo)
- :map(_.prop "tag_name")
- :get_or_throw "Failed to fetch latest release from GitHub API. Refer to :h mason-provider-errors for more information."
- end)
-
- return {
- with_receipt = function()
- ctx.receipt:with_primary_source {
- type = "github_release",
- repo = opts.repo,
- release = release,
- }
- end,
- release = release,
- }
-end
-
----@async
----@param opts {repo: string, version: Optional?, asset_file: string|fun(release: string):string}
-function M.release_file(opts)
- local source = M.release_version(opts)
- ---@type string
- local asset_file
- if type(opts.asset_file) == "function" then
- asset_file = opts.asset_file(source.release)
- elseif type(opts.asset_file) == "string" then
- asset_file = opts.asset_file --[[@as string]]
- end
- if not asset_file then
- error(
- (
- "Could not find which release file to download.\n"
- .. "Most likely the current operating system or architecture is not supported (%s_%s)."
- ):format(platform.sysname, platform.arch),
- 0
- )
- end
- local download_url = settings.current.github.download_url_template:format(opts.repo, source.release, asset_file)
- return {
- release = source.release,
- download_url = download_url,
- asset_file = asset_file,
- with_receipt = with_release_file_receipt(opts.repo, download_url, source.release),
- }
-end
-
----@async
----@param opts {repo: string, version: Optional?}
-function M.tag(opts)
- local ctx = installer.context()
- local tag = _.coalesce(opts.version, ctx.requested_version):or_else_get(function()
- return providers.github
- .get_latest_tag(opts.repo)
- :map(_.prop "tag")
- :get_or_throw "Failed to fetch latest tag from GitHub API."
- end)
-
- return {
- tag = tag,
- with_receipt = with_tag_receipt(opts.repo, tag),
- }
-end
-
----@param filename string
----@param processor async fun(opts: table)
-local function release_file_processor(filename, processor)
- ---@async
- ---@param opts {repo: string, version: Optional|nil, asset_file: string|fun(release: string):string}
- return function(opts)
- local release_file_source = M.release_file(opts)
- std.download_file(release_file_source.download_url, filename)
- processor(opts)
- return release_file_source
- end
-end
-
-M.unzip_release_file = release_file_processor("archive.zip", function()
- std.unzip("archive.zip", ".")
-end)
-
-M.untarzst_release_file = release_file_processor("archive.tar.zst", function(opts)
- std.untarzst("archive.tar.zst", { strip_components = opts.strip_components })
-end)
-
-M.untarxz_release_file = release_file_processor("archive.tar.xz", function(opts)
- std.untarxz("archive.tar.xz", { strip_components = opts.strip_components })
-end)
-
-M.untargz_release_file = release_file_processor("archive.tar.gz", function(opts)
- std.untar("archive.tar.gz", { strip_components = opts.strip_components })
-end)
-
----@async
----@param opts {repo: string, out_file:string, asset_file: string|fun(release: string):string}
-function M.download_release_file(opts)
- local release_file_source = M.release_file(opts)
- std.download_file(release_file_source.download_url, assert(opts.out_file, "out_file is required"))
- return release_file_source
-end
-
----@async
----@param opts {repo: string, out_file:string, asset_file: string|fun(release: string):string}
-function M.gunzip_release_file(opts)
- local release_file_source = M.release_file(opts)
- local gzipped_file = ("%s.gz"):format(assert(opts.out_file, "out_file must be specified"))
- std.download_file(release_file_source.download_url, gzipped_file)
- std.gunzip(gzipped_file)
- return release_file_source
-end
-
----@async
----@param receipt InstallReceipt<InstallReceiptGitHubReleaseFileSource>
-function M.check_outdated_primary_package_release(receipt)
- local source = receipt.primary_source
- if source.type ~= "github_release" and source.type ~= "github_release_file" then
- return Result.failure "Receipt does not have a primary source of type (github_release|github_release_file)."
- end
- return providers.github.get_latest_release(source.repo):map_catching(
- ---@param latest_release GitHubRelease
- function(latest_release)
- if source.release ~= latest_release.tag_name then
- return {
- name = source.repo,
- current_version = source.release,
- latest_version = latest_release.tag_name,
- }
- end
- error "Primary package is not outdated."
- end
- )
-end
-
----@async
----@param receipt InstallReceipt<InstallReceiptGitHubTagSource>
-function M.check_outdated_primary_package_tag(receipt)
- local source = receipt.primary_source
- if source.type ~= "github_tag" then
- return Result.failure "Receipt does not have a primary source of type github_tag."
- end
- return providers.github.get_latest_tag(source.repo):map(_.prop "tag"):map_catching(function(latest_tag)
- if source.tag ~= latest_tag then
- return {
- name = source.repo,
- current_version = source.tag,
- latest_version = latest_tag,
- }
- end
- error "Primary package is not outdated."
- end)
-end
-
-return M
diff --git a/lua/mason-core/managers/go/init.lua b/lua/mason-core/managers/go/init.lua
deleted file mode 100644
index 0452400d..00000000
--- a/lua/mason-core/managers/go/init.lua
+++ /dev/null
@@ -1,167 +0,0 @@
-local Optional = require "mason-core.optional"
-local _ = require "mason-core.functional"
-local a = require "mason-core.async"
-local installer = require "mason-core.installer"
-local platform = require "mason-core.platform"
-local spawn = require "mason-core.spawn"
-
-local M = {}
-
-local create_bin_path = _.if_else(_.always(platform.is.win), _.format "%s.exe", _.identity)
-
----@param packages string[]
-local function with_receipt(packages)
- return function()
- local ctx = installer.context()
- ctx.receipt:with_primary_source(ctx.receipt.go(packages[1]))
- -- Install secondary packages
- for i = 2, #packages do
- local pkg = packages[i]
- ctx.receipt:with_secondary_source(ctx.receipt.go(pkg))
- end
- end
-end
-
----@async
----@param packages { [number]: string, bin: string[]? } The go packages to install. The first item in this list will be the recipient of the requested version, if set.
-function M.packages(packages)
- return function()
- M.install(packages).with_receipt()
- end
-end
-
----@async
----@param packages { [number]: string, bin: string[]? } The go packages to install. The first item in this list will be the recipient of the requested version, if set.
-function M.install(packages)
- local ctx = installer.context()
- local env = {
- GOBIN = ctx.cwd:get(),
- }
- -- Install the head package
- do
- local head_package = packages[1]
- local version = ctx.requested_version:or_else "latest"
- ctx.spawn.go {
- "install",
- "-v",
- ("%s@%s"):format(head_package, version),
- env = env,
- }
- end
-
- -- Install secondary packages
- for i = 2, #packages do
- ctx.spawn.go { "install", "-v", ("%s@latest"):format(packages[i]), env = env }
- end
-
- if packages.bin then
- _.each(function(executable)
- ctx:link_bin(executable, create_bin_path(executable))
- end, packages.bin)
- end
-
- return {
- with_receipt = with_receipt(packages),
- }
-end
-
----@param output string The output from `go version -m` command.
-function M.parse_mod_version_output(output)
- ---@type {path: string[], mod: string[], dep: string[], build: string[]}
- local result = {}
- local lines = vim.split(output, "\n")
- for _, line in ipairs { unpack(lines, 2) } do
- local type, id, value = unpack(vim.split(line, "%s+", { trimempty = true }))
- if type and id then
- result[type] = result[type] or {}
- result[type][id] = value or ""
- end
- end
- return result
-end
-
-local trim_wildcard_suffix = _.gsub("/%.%.%.$", "")
-
----@param pkg string
-function M.parse_package_mod(pkg)
- if _.starts_with("github.com", pkg) then
- local components = _.split("/", pkg)
- return trim_wildcard_suffix(_.join("/", {
- components[1], -- github.com
- components[2], -- owner
- components[3], -- repo
- }))
- elseif _.starts_with("golang.org", pkg) then
- local components = _.split("/", pkg)
- return trim_wildcard_suffix(_.join("/", {
- components[1], -- golang.org
- components[2], -- x
- components[3], -- owner
- components[4], -- repo
- }))
- else
- -- selene: allow(if_same_then_else)
- local components = _.split("/", pkg)
- return trim_wildcard_suffix(_.join("/", {
- components[1],
- components[2],
- components[3],
- }))
- end
-end
-
----@async
----@param receipt InstallReceipt<InstallReceiptPackageSource>
----@param install_dir string
-function M.get_installed_primary_package_version(receipt, install_dir)
- a.scheduler()
- local normalized_pkg_name = trim_wildcard_suffix(receipt.primary_source.package)
- -- trims e.g. golang.org/x/tools/gopls to gopls
- local executable = vim.fn.fnamemodify(normalized_pkg_name, ":t")
- return spawn
- .go({
- "version",
- "-m",
- platform.is.win and ("%s.exe"):format(executable) or executable,
- cwd = install_dir,
- })
- :map_catching(function(result)
- local parsed_output = M.parse_mod_version_output(result.stdout)
- return Optional.of_nilable(parsed_output.mod[M.parse_package_mod(receipt.primary_source.package)])
- :or_else_throw "Failed to parse mod version"
- end)
-end
-
----@async
----@param receipt InstallReceipt<InstallReceiptPackageSource>
----@param install_dir string
-function M.check_outdated_primary_package(receipt, install_dir)
- local normalized_pkg_name = M.parse_package_mod(receipt.primary_source.package)
- return spawn
- .go({
- "list",
- "-json",
- "-m",
- ("%s@latest"):format(normalized_pkg_name),
- cwd = install_dir,
- })
- :map_catching(function(result)
- ---@type {Path: string, Version: string}
- local output = vim.json.decode(result.stdout)
- return Optional.of_nilable(output.Version)
- :map(function(latest_version)
- local installed_version = M.get_installed_primary_package_version(receipt, install_dir)
- :get_or_throw()
- if installed_version ~= latest_version then
- return {
- name = normalized_pkg_name,
- current_version = assert(installed_version, "missing installed_version"),
- latest_version = assert(latest_version, "missing latest_version"),
- }
- end
- end)
- :or_else_throw "Primary package is not outdated."
- end)
-end
-
-return M
diff --git a/lua/mason-core/managers/luarocks/init.lua b/lua/mason-core/managers/luarocks/init.lua
deleted file mode 100644
index 321346f9..00000000
--- a/lua/mason-core/managers/luarocks/init.lua
+++ /dev/null
@@ -1,137 +0,0 @@
-local Optional = require "mason-core.optional"
-local Result = require "mason-core.result"
-local _ = require "mason-core.functional"
-local installer = require "mason-core.installer"
-local path = require "mason-core.path"
-local platform = require "mason-core.platform"
-local spawn = require "mason-core.spawn"
-
-local M = {}
-
-local create_bin_path = _.compose(path.concat, function(executable)
- return _.append(executable, { "bin" })
-end, _.if_else(_.always(platform.is.win), _.format "%s.bat", _.identity))
-
----@param package string
-local function with_receipt(package)
- return function()
- local ctx = installer.context()
- ctx.receipt:with_primary_source(ctx.receipt.luarocks(package))
- end
-end
-
----@param package string The luarock package to install.
----@param opts { dev: boolean?, server: string?, bin: string[]? }?
-function M.package(package, opts)
- return function()
- return M.install(package, opts).with_receipt()
- end
-end
-
----@async
----@param pkg string: The luarock package to install.
----@param opts { dev: boolean?, server: string?, bin: string[]? }?
-function M.install(pkg, opts)
- opts = opts or {}
- local ctx = installer.context()
- ctx:promote_cwd()
- ctx.spawn.luarocks {
- "install",
- "--tree",
- ctx.cwd:get(),
- opts.dev and "--dev" or vim.NIL,
- opts.server and ("--server=%s"):format(opts.server) or vim.NIL,
- pkg,
- ctx.requested_version:or_else(vim.NIL),
- }
- if opts.bin then
- _.each(function(executable)
- ctx:link_bin(executable, create_bin_path(executable))
- end, opts.bin)
- end
- return {
- with_receipt = with_receipt(pkg),
- }
-end
-
----@alias InstalledLuarock {package: string, version: string, arch: string, nrepo: string, namespace: string}
-
----@type fun(output: string): InstalledLuarock[]
-M.parse_installed_rocks = _.compose(
- _.map(_.compose(
- -- https://github.com/luarocks/luarocks/blob/fbd3566a312e647cde57b5d774533731e1aa844d/src/luarocks/search.lua#L317
- _.zip_table { "package", "version", "arch", "nrepo", "namespace" },
- _.split "\t"
- )),
- _.split "\n"
-)
-
----@async
----@param receipt InstallReceipt<InstallReceiptPackageSource>
----@param install_dir string
-function M.get_installed_primary_package_version(receipt, install_dir)
- if receipt.primary_source.type ~= "luarocks" then
- return Result.failure "Receipt does not have a primary source of type luarocks"
- end
- local primary_package = receipt.primary_source.package
- return spawn
- .luarocks({
- "list",
- "--tree",
- install_dir,
- "--porcelain",
- })
- :map_catching(function(result)
- local luarocks = M.parse_installed_rocks(result.stdout)
- return Optional.of_nilable(_.find_first(_.prop_eq("package", primary_package), luarocks))
- :map(_.prop "version")
- :or_else_throw()
- end)
-end
-
----@alias OutdatedLuarock {name: string, installed: string, available: string, repo: string}
-
----@type fun(output: string): OutdatedLuarock[]
-M.parse_outdated_rocks = _.compose(
- _.map(_.compose(
- -- https://github.com/luarocks/luarocks/blob/fbd3566a312e647cde57b5d774533731e1aa844d/src/luarocks/cmd/list.lua#L59
- _.zip_table { "name", "installed", "available", "repo" },
- _.split "\t"
- )),
- _.split "\n"
-)
-
----@async
----@param receipt InstallReceipt<InstallReceiptPackageSource>
----@param install_dir string
-function M.check_outdated_primary_package(receipt, install_dir)
- if receipt.primary_source.type ~= "luarocks" then
- return Result.failure "Receipt does not have a primary source of type luarocks"
- end
- local primary_package = receipt.primary_source.package
- return spawn
- .luarocks({
- "list",
- "--outdated",
- "--tree",
- install_dir,
- "--porcelain",
- })
- :map_catching(function(result)
- local outdated_rocks = M.parse_outdated_rocks(result.stdout)
- return Optional.of_nilable(_.find_first(_.prop_eq("name", primary_package), outdated_rocks))
- :map(
- ---@param outdated_rock OutdatedLuarock
- function(outdated_rock)
- return {
- name = outdated_rock.name,
- current_version = assert(outdated_rock.installed, "missing installed luarock version"),
- latest_version = assert(outdated_rock.available, "missing available luarock version"),
- }
- end
- )
- :or_else_throw()
- end)
-end
-
-return M
diff --git a/lua/mason-core/managers/npm/init.lua b/lua/mason-core/managers/npm/init.lua
deleted file mode 100644
index bcefb55d..00000000
--- a/lua/mason-core/managers/npm/init.lua
+++ /dev/null
@@ -1,136 +0,0 @@
-local Result = require "mason-core.result"
-local _ = require "mason-core.functional"
-local installer = require "mason-core.installer"
-local path = require "mason-core.path"
-local platform = require "mason-core.platform"
-local providers = require "mason-core.providers"
-local spawn = require "mason-core.spawn"
-
-local list_copy = _.list_copy
-
-local M = {}
-
-local create_bin_path = _.compose(path.concat, function(executable)
- return _.append(executable, { "node_modules", ".bin" })
-end, _.if_else(_.always(platform.is.win), _.format "%s.cmd", _.identity))
-
----@async
----@param ctx InstallContext
-local function ensure_npm_root(ctx)
- if not (ctx.fs:dir_exists "node_modules" or ctx.fs:file_exists "package.json") then
- -- Create a package.json to set a boundary for where npm installs packages.
- ctx.spawn.npm { "init", "--yes", "--scope=mason" }
- ctx.stdio_sink.stdout "Initialized npm root\n"
- end
-end
-
----@param packages string[]
-local function with_receipt(packages)
- return function()
- local ctx = installer.context()
- ctx.receipt:with_primary_source(ctx.receipt.npm(packages[1]))
- for i = 2, #packages do
- ctx.receipt:with_secondary_source(ctx.receipt.npm(packages[i]))
- end
- end
-end
-
----@async
----@param packages { [number]: string, bin: string[]? } The npm packages to install. The first item in this list will be the recipient of the requested version, if set.
-function M.packages(packages)
- return function()
- return M.install(packages).with_receipt()
- end
-end
-
----@async
----@param packages { [number]: string, bin: string[]? } The npm packages to install. The first item in this list will be the recipient of the requested version, if set.
-function M.install(packages)
- local ctx = installer.context()
- local pkgs = list_copy(packages)
- ctx.requested_version:if_present(function(version)
- pkgs[1] = ("%s@%s"):format(pkgs[1], version)
- end)
-
- -- Use global-style. The reasons for this are:
- -- a) To avoid polluting the executables (aka bin-links) that npm creates.
- -- b) The installation is, after all, more similar to a "global" installation. We don't really gain
- -- any of the benefits of not using global style (e.g., deduping the dependency tree).
- --
- -- We write to .npmrc manually instead of going through npm because managing a local .npmrc file
- -- is a bit unreliable across npm versions (especially <7), so we take extra measures to avoid
- -- inadvertently polluting global npm config.
- ctx.fs:append_file(".npmrc", "global-style=true")
-
- ensure_npm_root(ctx)
- ctx.spawn.npm { "install", pkgs }
-
- if packages.bin then
- _.each(function(executable)
- ctx:link_bin(executable, create_bin_path(executable))
- end, packages.bin)
- end
-
- return {
- with_receipt = with_receipt(packages),
- }
-end
-
----@async
----@param exec_args string[] The arguments to pass to npm exec.
-function M.exec(exec_args)
- local ctx = installer.context()
- ctx.spawn.npm { "exec", "--yes", "--", exec_args }
-end
-
----@async
----@param script string The npm script to run.
-function M.run(script)
- local ctx = installer.context()
- ctx.spawn.npm { "run", script }
-end
-
----@async
----@param receipt InstallReceipt<InstallReceiptPackageSource>
----@param install_dir string
-function M.get_installed_primary_package_version(receipt, install_dir)
- if receipt.primary_source.type ~= "npm" then
- return Result.failure "Receipt does not have a primary source of type npm"
- end
- return spawn.npm({ "ls", "--json", cwd = install_dir }):map_catching(function(result)
- local npm_packages = vim.json.decode(result.stdout)
- return npm_packages.dependencies[receipt.primary_source.package].version
- end)
-end
-
----@async
----@param receipt InstallReceipt<InstallReceiptPackageSource>
----@param install_dir string
-function M.check_outdated_primary_package(receipt, install_dir)
- if receipt.primary_source.type ~= "npm" then
- return Result.failure "Receipt does not have a primary source of type npm"
- end
- local primary_package = receipt.primary_source.package
- return M.get_installed_primary_package_version(receipt, install_dir)
- :and_then(function(installed_version)
- return providers.npm.get_latest_version(primary_package):map(function(response)
- return {
- installed = installed_version,
- latest = response.version,
- }
- end)
- end)
- :and_then(function(versions)
- if versions.installed ~= versions.latest then
- return Result.success {
- name = primary_package,
- current_version = versions.installed,
- latest_version = versions.latest,
- }
- else
- return Result.failure "Primary package is not outdated."
- end
- end)
-end
-
-return M
diff --git a/lua/mason-core/managers/opam/init.lua b/lua/mason-core/managers/opam/init.lua
deleted file mode 100644
index ae742510..00000000
--- a/lua/mason-core/managers/opam/init.lua
+++ /dev/null
@@ -1,62 +0,0 @@
-local _ = require "mason-core.functional"
-local installer = require "mason-core.installer"
-local path = require "mason-core.path"
-local platform = require "mason-core.platform"
-
-local M = {}
-
-local list_copy = _.list_copy
-
-local create_bin_path = _.compose(path.concat, function(executable)
- return _.append(executable, { "bin" })
-end, _.if_else(_.always(platform.is.win), _.format "%s.exe", _.identity))
-
----@param packages string[]
-local function with_receipt(packages)
- return function()
- local ctx = installer.context()
- ctx.receipt:with_primary_source(ctx.receipt.opam(packages[1]))
- for i = 2, #packages do
- ctx.receipt:with_secondary_source(ctx.receipt.opam(packages[i]))
- end
- end
-end
-
----@async
----@param packages { [number]: string, bin: string[]? } The opam packages to install. The first item in this list will be the recipient of the requested version, if set.
-function M.packages(packages)
- return function()
- return M.install(packages).with_receipt()
- end
-end
-
----@async
----@param packages { [number]: string, bin: string[]? } The opam packages to install. The first item in this list will be the recipient of the requested version, if set.
-function M.install(packages)
- local ctx = installer.context()
- local pkgs = list_copy(packages)
-
- ctx.requested_version:if_present(function(version)
- pkgs[1] = ("%s.%s"):format(pkgs[1], version)
- end)
-
- ctx.spawn.opam {
- "install",
- "--destdir=.",
- "--yes",
- "--verbose",
- pkgs,
- }
-
- if packages.bin then
- _.each(function(executable)
- ctx:link_bin(executable, create_bin_path(executable))
- end, packages.bin)
- end
-
- return {
- with_receipt = with_receipt(packages),
- }
-end
-
-return M
diff --git a/lua/mason-core/managers/pip3/init.lua b/lua/mason-core/managers/pip3/init.lua
deleted file mode 100644
index 813bc9ea..00000000
--- a/lua/mason-core/managers/pip3/init.lua
+++ /dev/null
@@ -1,173 +0,0 @@
-local Optional = require "mason-core.optional"
-local Result = require "mason-core.result"
-local _ = require "mason-core.functional"
-local a = require "mason-core.async"
-local installer = require "mason-core.installer"
-local path = require "mason-core.path"
-local platform = require "mason-core.platform"
-local providers = require "mason-core.providers"
-local settings = require "mason.settings"
-local spawn = require "mason-core.spawn"
-
-local VENV_DIR = "venv"
-
-local M = {}
-
-local create_bin_path = _.compose(path.concat, function(executable)
- return _.append(executable, { VENV_DIR, platform.is.win and "Scripts" or "bin" })
-end, _.if_else(_.always(platform.is.win), _.format "%s.exe", _.identity))
-
----@param packages string[]
-local function with_receipt(packages)
- return function()
- local ctx = installer.context()
- ctx.receipt:with_primary_source(ctx.receipt.pip3(packages[1]))
- for i = 2, #packages do
- ctx.receipt:with_secondary_source(ctx.receipt.pip3(packages[i]))
- end
- end
-end
-
----@async
----@param packages { [number]: string, bin: string[]? } The pip packages to install. The first item in this list will be the recipient of the requested version, if set.
-function M.packages(packages)
- return function()
- return M.install(packages).with_receipt()
- end
-end
-
----@async
----@param packages { [number]: string, bin: string[]? } The pip packages to install. The first item in this list will be the recipient of the requested version, if set.
-function M.install(packages)
- local ctx = installer.context()
- local pkgs = _.list_copy(packages)
-
- ctx.requested_version:if_present(function(version)
- pkgs[1] = ("%s==%s"):format(pkgs[1], version)
- end)
-
- a.scheduler()
-
- local executables = platform.is.win and { "python", "python3" } or { "python3", "python" }
-
- -- pip3 will hardcode the full path to venv executables, so we need to promote cwd to make sure pip uses the final destination path.
- ctx:promote_cwd()
-
- -- Find first executable that manages to create venv
- local executable = _.find_first(function(executable)
- return pcall(ctx.spawn[executable], { "-m", "venv", VENV_DIR })
- end, executables)
-
- Optional.of_nilable(executable)
- :if_present(function()
- if settings.current.pip.upgrade_pip then
- ctx.spawn.python {
- "-m",
- "pip",
- "--disable-pip-version-check",
- "install",
- "-U",
- settings.current.pip.install_args,
- "pip",
- with_paths = { M.venv_path(ctx.cwd:get()) },
- }
- end
- ctx.spawn.python {
- "-m",
- "pip",
- "--disable-pip-version-check",
- "install",
- "-U",
- settings.current.pip.install_args,
- pkgs,
- with_paths = { M.venv_path(ctx.cwd:get()) },
- }
- end)
- :or_else_throw "Unable to create python3 venv environment."
-
- if packages.bin then
- _.each(function(bin)
- ctx:link_bin(bin, create_bin_path(bin))
- end, packages.bin)
- end
-
- return {
- with_receipt = with_receipt(packages),
- }
-end
-
----@param pkg string
----@return string
-function M.normalize_package(pkg)
- -- https://stackoverflow.com/a/60307740
- local s = pkg:gsub("%[.*%]", "")
- return s
-end
-
----@async
----@param receipt InstallReceipt<InstallReceiptPackageSource>
----@param install_dir string
-function M.check_outdated_primary_package(receipt, install_dir)
- if receipt.primary_source.type ~= "pip3" then
- 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 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 = versions.current,
- latest_version = versions.latest,
- }
- else
- return Result.failure "Primary package is not outdated."
- end
- end)
- end)
-end
-
----@async
----@param receipt InstallReceipt<InstallReceiptPackageSource>
----@param install_dir string
-function M.get_installed_primary_package_version(receipt, install_dir)
- if receipt.primary_source.type ~= "pip3" then
- return Result.failure "Receipt does not have a primary source of type pip3"
- end
- return spawn
- .python({
- "-m",
- "pip",
- "list",
- "--format=json",
- cwd = install_dir,
- with_paths = { M.venv_path(install_dir) },
- })
- :map_catching(function(result)
- local pip_packages = vim.json.decode(result.stdout)
- local normalized_pip_package = M.normalize_package(receipt.primary_source.package)
- local pip_package = _.find_first(function(pkg)
- return pkg.name == normalized_pip_package
- end, pip_packages)
- return Optional.of_nilable(pip_package)
- :map(function(pkg)
- return pkg.version
- end)
- :or_else_throw "Unable to find pip package."
- end)
-end
-
----@param install_dir string
-function M.venv_path(install_dir)
- return path.concat { install_dir, VENV_DIR, platform.is.win and "Scripts" or "bin" }
-end
-
-return M
diff --git a/lua/mason-core/managers/std/init.lua b/lua/mason-core/managers/std/init.lua
deleted file mode 100644
index b3116d7a..00000000
--- a/lua/mason-core/managers/std/init.lua
+++ /dev/null
@@ -1,196 +0,0 @@
-local Result = require "mason-core.result"
-local a = require "mason-core.async"
-local fetch = require "mason-core.fetch"
-local installer = require "mason-core.installer"
-local path = require "mason-core.path"
-local platform = require "mason-core.platform"
-local powershell = require "mason-core.managers.powershell"
-
-local M = {}
-
-local function with_system_executable_receipt(executable)
- return function()
- local ctx = installer.context()
- ctx.receipt:with_primary_source(ctx.receipt.system(executable))
- end
-end
-
----@async
----@param executable string
----@param opts {help_url:string?}?
-function M.ensure_executable(executable, opts)
- local ctx = installer.context()
- opts = opts or {}
- a.scheduler()
- if vim.fn.executable(executable) ~= 1 then
- ctx.stdio_sink.stderr(("%s was not found in path.\n"):format(executable))
- if opts.help_url then
- ctx.stdio_sink.stderr(("See %s for installation instructions.\n"):format(opts.help_url))
- end
- error("Installation failed: system executable was not found.", 0)
- end
-
- return {
- with_receipt = with_system_executable_receipt(executable),
- }
-end
-
----@async
----@param url string
----@param out_file string
-function M.download_file(url, out_file)
- local ctx = installer.context()
- ctx.stdio_sink.stdout(("Downloading file %q…\n"):format(url))
- fetch(url, {
- out_file = path.concat { ctx.cwd:get(), out_file },
- })
- :map_err(function(err)
- return ("Failed to download file %q.\n%s"):format(url, err)
- end)
- :get_or_throw()
-end
-
----@async
----@param file string
----@param dest string
-function M.unzip(file, dest)
- local ctx = installer.context()
- platform.when {
- unix = function()
- ctx.spawn.unzip { "-d", dest, file }
- end,
- win = function()
- powershell.command(
- ("Microsoft.PowerShell.Archive\\Expand-Archive -Path %q -DestinationPath %q"):format(file, dest),
- {},
- ctx.spawn
- )
- end,
- }
- pcall(function()
- -- make sure the .zip archive doesn't linger
- ctx.fs:unlink(file)
- end)
-end
-
----@param file string
-local function win_decompress(file)
- local ctx = installer.context()
- Result.run_catching(function()
- ctx.spawn.gzip { "-d", file }
- end)
- :recover_catching(function()
- ctx.spawn["7z"] { "x", "-y", "-r", file }
- end)
- :recover_catching(function()
- ctx.spawn.peazip { "-ext2here", path.concat { ctx.cwd:get(), file } } -- peazip requires absolute paths
- end)
- :recover_catching(function()
- ctx.spawn.wzunzip { file }
- end)
- :recover_catching(function()
- ctx.spawn.winrar { "e", file }
- end)
- :get_or_throw(("Unable to unpack %s."):format(file))
-end
-
----@async
----@param file string
----@param opts { strip_components?: integer }?
-function M.untar(file, opts)
- opts = opts or {}
- local ctx = installer.context()
- ctx.spawn.tar {
- opts.strip_components and { "--strip-components", opts.strip_components } or vim.NIL,
- "--no-same-owner",
- "-xvf",
- file,
- }
- pcall(function()
- ctx.fs:unlink(file)
- end)
-end
-
----@async
----@param file string
----@param opts { strip_components?: integer }?
-function M.untarzst(file, opts)
- opts = opts or {}
- platform.when {
- unix = function()
- M.untar(file, opts)
- end,
- win = function()
- local ctx = installer.context()
- local uncompressed_tar = file:gsub("%.zst$", "")
- ctx.spawn.zstd { "-dfo", uncompressed_tar, file }
- M.untar(uncompressed_tar, opts)
- end,
- }
-end
-
----@async
----@param file string
----@param opts { strip_components?: integer }?
-function M.untarxz(file, opts)
- opts = opts or {}
- local ctx = installer.context()
- platform.when {
- unix = function()
- M.untar(file, opts)
- end,
- win = function()
- Result.run_catching(function()
- win_decompress(file) -- unpack .tar.xz to .tar
- local uncompressed_tar = file:gsub("%.xz$", "")
- M.untar(uncompressed_tar, opts)
- end):recover(function()
- ctx.spawn.arc {
- "unarchive",
- opts.strip_components and { "--strip-components", opts.strip_components } or vim.NIL,
- file,
- }
- pcall(function()
- ctx.fs:unlink(file)
- end)
- end)
- end,
- }
-end
-
----@async
----@param file string
-function M.gunzip(file)
- platform.when {
- unix = function()
- local ctx = installer.context()
- ctx.spawn.gzip { "-d", file }
- end,
- win = function()
- win_decompress(file)
- end,
- }
-end
-
----@async
----@param flags string The chmod flag to apply.
----@param files string[] A list of relative paths to apply the chmod on.
-function M.chmod(flags, files)
- if platform.is.unix then
- local ctx = installer.context()
- ctx.spawn.chmod { flags, files }
- end
-end
-
----@async
----Wrapper around vim.ui.select.
----@param items table
----@params opts
-function M.select(items, opts)
- assert(not platform.is_headless, "Tried to prompt for user input while in headless mode.")
- a.scheduler()
- local async_select = a.promisify(vim.ui.select)
- return async_select(items, opts)
-end
-
-return M
diff --git a/tests/mason-core/installer/context_spec.lua b/tests/mason-core/installer/context_spec.lua
index af99089f..646f7e30 100644
--- a/tests/mason-core/installer/context_spec.lua
+++ b/tests/mason-core/installer/context_spec.lua
@@ -1,8 +1,7 @@
local match = require "luassert.match"
local path = require "mason-core.path"
-local pip3 = require "mason-core.managers.pip3"
+local pypi = require "mason-core.installer.managers.pypi"
local registry = require "mason-registry"
-local std = require "mason-core.managers.std"
local stub = require "luassert.stub"
describe("installer", function()
@@ -21,9 +20,9 @@ describe("installer", function()
stub(ctx.fs, "write_file")
stub(ctx.fs, "file_exists")
stub(ctx.fs, "dir_exists")
+ stub(ctx.fs, "chmod_exec")
ctx.fs.file_exists.on_call_with(match.is_ref(ctx.fs), "my-executable").returns(false)
ctx.fs.dir_exists.on_call_with(match.is_ref(ctx.fs), "my-executable").returns(false)
- stub(std, "chmod")
ctx:write_shell_exec_wrapper("my-executable", "bash -c 'echo $GREETING'", {
GREETING = "Hello World!",
@@ -52,7 +51,6 @@ exec bash -c 'echo $GREETING' "$@"]]
stub(ctx.fs, "dir_exists")
ctx.fs.file_exists.on_call_with(match.is_ref(ctx.fs), "my-executable").returns(false)
ctx.fs.dir_exists.on_call_with(match.is_ref(ctx.fs), "my-executable").returns(false)
- stub(std, "chmod")
ctx:write_shell_exec_wrapper("my-executable", "cmd.exe /C echo %GREETING%", {
GREETING = "Hello World!",
@@ -156,7 +154,7 @@ cmd.exe /C echo %GREETING% %*]]
assert.spy(ctx.write_shell_exec_wrapper).was_called_with(
match.is_ref(ctx),
"my-wrapper-script",
- ("%q -m my-module"):format(path.concat { pip3.venv_path(dummy:get_install_path()), "python" })
+ ("%q -m my-module"):format(path.concat { pypi.venv_path(dummy:get_install_path()), "python" })
)
end)
diff --git a/tests/mason-core/managers/powershell_spec.lua b/tests/mason-core/installer/managers/powershell_spec.lua
index 56ec243e..86bbe1f9 100644
--- a/tests/mason-core/managers/powershell_spec.lua
+++ b/tests/mason-core/installer/managers/powershell_spec.lua
@@ -6,8 +6,8 @@ local stub = require "luassert.stub"
describe("powershell manager", function()
local function powershell()
- package.loaded["mason-core.managers.powershell"] = nil
- return require "mason-core.managers.powershell"
+ package.loaded["mason-core.installer.managers.powershell"] = nil
+ return require "mason-core.installer.managers.powershell"
end
it("should use pwsh if available", function()
diff --git a/tests/mason-core/managers/cargo_spec.lua b/tests/mason-core/managers/cargo_spec.lua
deleted file mode 100644
index 92d04588..00000000
--- a/tests/mason-core/managers/cargo_spec.lua
+++ /dev/null
@@ -1,350 +0,0 @@
-local Result = require "mason-core.result"
-local _ = require "mason-core.functional"
-local cargo = require "mason-core.managers.cargo"
-local cargo_client = require "mason-core.managers.cargo.client"
-local github = require "mason-core.managers.github"
-local github_client = require "mason-core.managers.github.client"
-local installer = require "mason-core.installer"
-local match = require "luassert.match"
-local mock = require "luassert.mock"
-local path = require "mason-core.path"
-local spawn = require "mason-core.spawn"
-local spy = require "luassert.spy"
-local stub = require "luassert.stub"
-
-describe("cargo manager", function()
- it(
- "should call cargo install",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, cargo.crate "my-crate")
- assert.spy(ctx.spawn.cargo).was_called(1)
- assert.spy(ctx.spawn.cargo).was_called_with {
- "install",
- "--root",
- ".",
- "--locked",
- { "--version", "42.13.37" },
- vim.NIL, -- --git
- vim.NIL, -- --features
- "my-crate",
- }
- end)
- )
-
- it(
- "should call cargo install with git source",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle)
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, cargo.crate("my-crate", { git = { url = "https://my-crate.git" } }))
- assert.spy(ctx.spawn.cargo).was_called(1)
- assert.spy(ctx.spawn.cargo).was_called_with {
- "install",
- "--root",
- ".",
- "--locked",
- vim.NIL, -- version
- { "--git", "https://my-crate.git" },
- vim.NIL, -- --features
- "my-crate",
- }
- end)
- )
-
- it(
- "should call cargo install with git source and a specific crate",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle)
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, cargo.crate("crate-name", { git = { url = "https://my-crate.git" } }))
- assert.spy(ctx.spawn.cargo).was_called(1)
- assert.spy(ctx.spawn.cargo).was_called_with {
- "install",
- "--root",
- ".",
- "--locked",
- vim.NIL, -- version
- { "--git", "https://my-crate.git" },
- vim.NIL, -- --features
- "crate-name",
- }
- end)
- )
-
- it(
- "should respect options",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, cargo.crate("my-crate", { features = "lsp" }))
- assert.spy(ctx.spawn.cargo).was_called(1)
- assert.spy(ctx.spawn.cargo).was_called_with {
- "install",
- "--root",
- ".",
- "--locked",
- { "--version", "42.13.37" },
- vim.NIL, -- --git
- { "--features", "lsp" },
- "my-crate",
- }
- end)
- )
-
- it(
- "should target tagged git crates",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- stub(github, "tag")
- github.tag.returns { tag = "v2.1.1", with_receipt = mockx.just_runs }
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(
- ctx,
- cargo.crate("my-crate", {
- git = {
- url = "https://github.com/crate/my-crate",
- tag = true,
- },
- features = "lsp",
- })
- )
- assert.spy(ctx.spawn.cargo).was_called_with {
- "install",
- "--root",
- ".",
- "--locked",
- { "--tag", "v2.1.1" },
- { "--git", "https://github.com/crate/my-crate" }, -- --git
- { "--features", "lsp" },
- "my-crate",
- }
- end)
- )
-
- it(
- "should provide receipt information",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle)
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, cargo.crate "main-package")
- assert.same({
- type = "cargo",
- package = "main-package",
- }, ctx.receipt.primary_source)
- end)
- )
-end)
-
-describe("cargo version check", function()
- it("parses cargo installed packages output", function()
- assert.same(
- {
- ["bat"] = { name = "bat", version = "0.18.3" },
- ["exa"] = { name = "exa", version = "0.10.1" },
- ["git-select-branch"] = { name = "git-select-branch", version = "0.1.1" },
- ["hello_world"] = { name = "hello_world", version = "0.0.1" },
- ["rust-analyzer"] = {
- name = "rust-analyzer",
- version = "187bee0b",
- github_ref = { owner = "rust-lang", repo = "rust-analyzer", ref = "187bee0b" },
- },
- ["move-analyzer"] = {
- name = "move-analyzer",
- version = "3cef7fa8",
- github_ref = { owner = "move-language", repo = "move", ref = "3cef7fa8" },
- },
- ["stylua"] = { name = "stylua", version = "0.11.2" },
- ["zoxide"] = { name = "zoxide", version = "0.5.0" },
- },
- cargo.parse_installed_crates(_.dedent [[
- bat v0.18.3:
- bat
- exa v0.10.1:
- exa
- git-select-branch v0.1.1:
- git-select-branch
- hello_world v0.0.1 (/private/var/folders/ky/s6yyhm_d24d0jsrql4t8k4p40000gn/T/tmp.LGbguATJHj):
- hello_world
- move-analyzer v1.0.0 (https://github.com/move-language/move#3cef7fa8):
- move-analyzer
- rust-analyzer v0.0.0 (https://github.com/rust-lang/rust-analyzer?tag=2022-09-19#187bee0b):
- rust-analyzer
- stylua v0.11.2:
- stylua
- zoxide v0.5.0:
- zoxide
- ]])
- )
- end)
-
- it(
- "should return current version",
- async_test(function()
- stub(spawn, "cargo")
- spawn.cargo.returns(Result.success {
- stdout = _.dedent [[
- flux-lsp v0.8.8 (https://github.com/influxdata/flux-lsp#4e452f07):
- flux-lsp
- ]],
- })
-
- local result = cargo.get_installed_primary_package_version(
- mock.new {
- primary_source = mock.new {
- type = "cargo",
- package = "https://github.com/influxdata/flux-lsp",
- },
- },
- path.package_prefix "dummy"
- )
-
- assert.spy(spawn.cargo).was_called(1)
- assert.spy(spawn.cargo).was_called_with(match.tbl_containing {
- "install",
- "--list",
- "--root",
- ".",
- cwd = path.package_prefix "dummy",
- })
- assert.is_true(result:is_success())
- assert.equals("4e452f07", result:get_or_nil())
- end)
- )
-
- it(
- "should return outdated primary package",
- async_test(function()
- stub(spawn, "cargo")
- spawn.cargo.returns(Result.success {
- stdout = _.dedent [[
- lelwel v0.4.0:
- lelwel-ls
- ]],
- })
- stub(cargo_client, "fetch_crate")
- cargo_client.fetch_crate.returns(Result.success {
- crate = {
- id = "lelwel",
- max_stable_version = "0.4.2",
- max_version = "0.4.2",
- newest_version = "0.4.2",
- },
- })
-
- local result = cargo.check_outdated_primary_package(
- mock.new {
- primary_source = mock.new {
- type = "cargo",
- package = "lelwel",
- },
- },
- path.package_prefix "dummy"
- )
-
- assert.spy(spawn.cargo).was_called(1)
- assert.spy(spawn.cargo).was_called_with(match.tbl_containing {
- "install",
- "--list",
- "--root",
- ".",
- cwd = path.package_prefix "dummy",
- })
- assert.is_true(result:is_success())
- assert.is_true(match.tbl_containing {
- current_version = "0.4.0",
- latest_version = "0.4.2",
- name = "lelwel",
- }(result:get_or_nil()))
- end)
- )
-
- it(
- "should recognize up-to-date crates",
- async_test(function()
- stub(spawn, "cargo")
- spawn.cargo.returns(Result.success {
- stdout = _.dedent [[
- lelwel v0.4.0:
- lelwel-ls
- ]],
- })
- stub(cargo_client, "fetch_crate")
- cargo_client.fetch_crate.returns(Result.success {
- crate = {
- id = "lelwel",
- max_stable_version = "0.4.0",
- max_version = "0.4.0",
- newest_version = "0.4.0",
- },
- })
-
- local result = cargo.check_outdated_primary_package(
- mock.new {
- primary_source = mock.new {
- type = "cargo",
- package = "lelwel",
- },
- },
- path.package_prefix "dummy"
- )
-
- assert.is_true(result:is_failure())
- assert.equals("Primary package is not outdated.", result:err_or_nil())
- end)
- )
-
- it(
- "should return outdated primary package from git source",
- async_test(function()
- stub(spawn, "cargo")
- spawn.cargo.returns(Result.success {
- stdout = _.dedent [[
- move-analyzer v1.0.0 (https://github.com/move-language/move#3cef7fa8):
- move-analyzer
- ]],
- })
-
- stub(github_client, "fetch_commits")
- github_client.fetch_commits
- .on_call_with("move-language/move", { page = 1, per_page = 1 })
- .returns(Result.success {
- {
- sha = "b243f1fb",
- },
- })
-
- local result = cargo.check_outdated_primary_package(
- mock.new {
- primary_source = mock.new {
- type = "cargo",
- package = "move-analyzer",
- },
- },
- path.package_prefix "dummy"
- )
-
- assert.spy(spawn.cargo).was_called(1)
- assert.spy(spawn.cargo).was_called_with(match.tbl_containing {
- "install",
- "--list",
- "--root",
- ".",
- cwd = path.package_prefix "dummy",
- })
- assert.is_true(result:is_success())
- assert.is_true(match.tbl_containing {
- current_version = "3cef7fa8",
- latest_version = "b243f1fb",
- name = "move-analyzer",
- }(result:get_or_nil()))
- end)
- )
-end)
diff --git a/tests/mason-core/managers/composer_spec.lua b/tests/mason-core/managers/composer_spec.lua
deleted file mode 100644
index 5e5b97ba..00000000
--- a/tests/mason-core/managers/composer_spec.lua
+++ /dev/null
@@ -1,173 +0,0 @@
-local Result = require "mason-core.result"
-local composer = require "mason-core.managers.composer"
-local installer = require "mason-core.installer"
-local mock = require "luassert.mock"
-local path = require "mason-core.path"
-local spawn = require "mason-core.spawn"
-local spy = require "luassert.spy"
-local stub = require "luassert.stub"
-
-describe("composer manager", function()
- it(
- "should call composer require",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- ctx.fs.file_exists = spy.new(mockx.returns(false))
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(
- ctx,
- composer.packages { "main-package", "supporting-package", "supporting-package2" }
- )
- assert.spy(ctx.spawn.composer).was_called(2)
- assert.spy(ctx.spawn.composer).was_called_with {
- "init",
- "--no-interaction",
- "--stability=stable",
- }
- assert.spy(ctx.spawn.composer).was_called_with {
- "require",
- {
- "main-package:42.13.37",
- "supporting-package",
- "supporting-package2",
- },
- }
- end)
- )
-
- it(
- "should provide receipt information",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(
- ctx,
- composer.packages { "main-package", "supporting-package", "supporting-package2" }
- )
- assert.same({
- type = "composer",
- package = "main-package",
- }, ctx.receipt.primary_source)
- assert.same({
- {
- type = "composer",
- package = "supporting-package",
- },
- {
- type = "composer",
- package = "supporting-package2",
- },
- }, ctx.receipt.secondary_sources)
- end)
- )
-end)
-
-describe("composer version check", function()
- it(
- "should return current version",
- async_test(function()
- stub(spawn, "composer")
- spawn.composer.returns(Result.success {
- stdout = [[
- {
- "name": "vimeo/psalm",
- "versions": [
- "4.0.0"
- ]
- }
- ]],
- })
-
- local result = composer.get_installed_primary_package_version(
- mock.new {
- primary_source = mock.new {
- type = "composer",
- package = "vimeo/psalm",
- },
- },
- path.package_prefix "dummy"
- )
-
- assert.spy(spawn.composer).was_called(1)
- assert.spy(spawn.composer).was_called_with {
- "info",
- "--format=json",
- "vimeo/psalm",
- cwd = path.package_prefix "dummy",
- }
- assert.is_true(result:is_success())
- assert.equals("4.0.0", result:get_or_nil())
- end)
- )
-
- it(
- "should return outdated primary package",
- async_test(function()
- stub(spawn, "composer")
- spawn.composer.returns(Result.success {
- stdout = [[
- {
- "installed": [
- {
- "name": "vimeo/psalm",
- "version": "4.0.0",
- "latest": "4.22.0",
- "latest-status": "semver-safe-update",
- "description": "A static analysis tool for finding errors in PHP applications"
- }
- ]
- }
- ]],
- })
-
- local result = composer.check_outdated_primary_package(
- mock.new {
- primary_source = mock.new {
- type = "composer",
- package = "vimeo/psalm",
- },
- },
- path.package_prefix "dummy"
- )
-
- assert.spy(spawn.composer).was_called(1)
- assert.spy(spawn.composer).was_called_with {
- "outdated",
- "--no-interaction",
- "--format=json",
- cwd = path.package_prefix "dummy",
- }
- assert.is_true(result:is_success())
- assert.same({
- name = "vimeo/psalm",
- current_version = "4.0.0",
- latest_version = "4.22.0",
- }, result:get_or_nil())
- end)
- )
-
- it(
- "should return failure if primary package is not outdated",
- async_test(function()
- stub(spawn, "composer")
- spawn.composer.returns(Result.success {
- stdout = [[{"installed": []}]],
- })
-
- local result = composer.check_outdated_primary_package(
- mock.new {
- primary_source = mock.new {
- type = "composer",
- package = "vimeo/psalm",
- },
- },
- path.package_prefix "dummy"
- )
-
- assert.is_true(result:is_failure())
- assert.equals("Primary package is not outdated.", result:err_or_nil())
- end)
- )
-end)
diff --git a/tests/mason-core/managers/dotnet_spec.lua b/tests/mason-core/managers/dotnet_spec.lua
deleted file mode 100644
index b6e0f8c0..00000000
--- a/tests/mason-core/managers/dotnet_spec.lua
+++ /dev/null
@@ -1,38 +0,0 @@
-local dotnet = require "mason-core.managers.dotnet"
-local installer = require "mason-core.installer"
-
-describe("dotnet manager", function()
- it(
- "should call dotnet tool update",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, dotnet.package "main-package")
- assert.spy(ctx.spawn.dotnet).was_called(1)
- assert.spy(ctx.spawn.dotnet).was_called_with {
- "tool",
- "update",
- "--ignore-failed-sources",
- "--tool-path",
- ".",
- { "--version", "42.13.37" },
- "main-package",
- }
- end)
- )
-
- it(
- "should provide receipt information",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, dotnet.package "main-package")
- assert.same({
- type = "dotnet",
- package = "main-package",
- }, ctx.receipt.primary_source)
- end)
- )
-end)
diff --git a/tests/mason-core/managers/gem_spec.lua b/tests/mason-core/managers/gem_spec.lua
deleted file mode 100644
index a99bf5e9..00000000
--- a/tests/mason-core/managers/gem_spec.lua
+++ /dev/null
@@ -1,190 +0,0 @@
-local Result = require "mason-core.result"
-local _ = require "mason-core.functional"
-local api = require "mason-registry.api"
-local gem = require "mason-core.managers.gem"
-local installer = require "mason-core.installer"
-local match = require "luassert.match"
-local mock = require "luassert.mock"
-local spawn = require "mason-core.spawn"
-local spy = require "luassert.spy"
-local stub = require "luassert.stub"
-
-describe("gem manager", function()
- it(
- "should call gem install",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, gem.packages { "main-package", "supporting-package", "supporting-package2" })
- assert.spy(ctx.spawn.gem).was_called(1)
- assert.spy(ctx.spawn.gem).was_called_with(match.tbl_containing {
- "install",
- "--no-user-install",
- "--no-format-executable",
- "--install-dir=.",
- "--bindir=bin",
- "--no-document",
- match.tbl_containing {
- "main-package:42.13.37",
- "supporting-package",
- "supporting-package2",
- },
- })
- end)
- )
-
- it(
- "should provide receipt information",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, gem.packages { "main-package", "supporting-package", "supporting-package2" })
- assert.same({
- type = "gem",
- package = "main-package",
- }, ctx.receipt.primary_source)
- assert.same({
- {
- type = "gem",
- package = "supporting-package",
- },
- {
- type = "gem",
- package = "supporting-package2",
- },
- }, ctx.receipt.secondary_sources)
- end)
- )
-end)
-
-describe("gem version check", function()
- it(
- "should return current version",
- async_test(function()
- stub(spawn, "gem")
- spawn.gem.returns(Result.success {
- stdout = _.dedent [[
- shellwords (default: 0.1.0)
- singleton (default: 0.1.1)
- solargraph (0.44.0)
- stringio (default: 3.0.1)
- strscan (default: 3.0.1)
- ]],
- })
-
- local result = gem.get_installed_primary_package_version(
- mock.new {
- primary_source = mock.new {
- type = "gem",
- package = "solargraph",
- },
- },
- "/tmp/install/dir"
- )
-
- assert.spy(spawn.gem).was_called(1)
- assert.spy(spawn.gem).was_called_with(match.tbl_containing {
- "list",
- cwd = "/tmp/install/dir",
- env = match.tbl_containing {
- GEM_HOME = "/tmp/install/dir",
- GEM_PATH = "/tmp/install/dir",
- PATH = match.matches "^/tmp/install/dir/bin:.*$",
- },
- })
- assert.is_true(result:is_success())
- assert.equals("0.44.0", result:get_or_nil())
- end)
- )
-
- it(
- "should return outdated primary package",
- async_test(function()
- stub(spawn, "gem")
- spawn.gem.returns(Result.success {
- stdout = _.dedent [[
- shellwords (default: 0.1.0)
- singleton (default: 0.1.1)
- solargraph (0.44.0)
- stringio (default: 3.0.1)
- strscan (default: 3.0.1)
- ]],
- })
- stub(api, "get")
- api.get.on_call_with("/api/rubygems/solargraph/versions/latest").returns(Result.success {
- name = "solargraph",
- version = "0.44.3",
- })
-
- local result = gem.check_outdated_primary_package(
- mock.new {
- primary_source = mock.new {
- type = "gem",
- package = "solargraph",
- },
- },
- "/tmp/install/dir"
- )
-
- assert.is_true(result:is_success())
- assert.same({
- name = "solargraph",
- current_version = "0.44.0",
- latest_version = "0.44.3",
- }, result:get_or_nil())
- end)
- )
-
- it(
- "should return failure if primary package is not outdated",
- async_test(function()
- stub(spawn, "gem")
- spawn.gem.returns(Result.success {
- stdout = _.dedent [[
- shellwords (default: 0.1.0)
- singleton (default: 0.1.1)
- solargraph (0.44.0)
- stringio (default: 3.0.1)
- strscan (default: 3.0.1)
- ]],
- })
- stub(api, "get")
- api.get.on_call_with("/api/rubygems/solargraph/versions/latest").returns(Result.success {
- name = "solargraph",
- version = "0.44.0",
- })
-
- local result = gem.check_outdated_primary_package(
- mock.new {
- primary_source = mock.new {
- type = "gem",
- package = "solargraph",
- },
- },
- "/tmp/install/dir"
- )
-
- assert.is_true(result:is_failure())
- assert.equals("Primary package is not outdated.", result:err_or_nil())
- end)
- )
-
- it("should parse gem list output", function()
- assert.same(
- {
- ["solargraph"] = "0.44.3",
- ["unicode-display_width"] = "2.1.0",
- },
- gem.parse_gem_list_output [[
-
-*** LOCAL GEMS ***
-
-nokogiri (1.13.3 arm64-darwin)
-solargraph (0.44.3)
-unicode-display_width (2.1.0)
-]]
- )
- end)
-end)
diff --git a/tests/mason-core/managers/git_spec.lua b/tests/mason-core/managers/git_spec.lua
deleted file mode 100644
index 50d2470f..00000000
--- a/tests/mason-core/managers/git_spec.lua
+++ /dev/null
@@ -1,181 +0,0 @@
-local Result = require "mason-core.result"
-local _ = require "mason-core.functional"
-local installer = require "mason-core.installer"
-local mock = require "luassert.mock"
-local spawn = require "mason-core.spawn"
-local stub = require "luassert.stub"
-
-local git = require "mason-core.managers.git"
-
-describe("git manager", function()
- it(
- "should fail if no git repo provided",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle)
- local err = assert.has_error(function()
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, function()
- git.clone {}
- end)
- end)
- assert.equals("No git URL provided.", err)
- assert.spy(ctx.spawn.git).was_not_called()
- end)
- )
-
- it(
- "should clone provided repo",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle)
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, function()
- git.clone { "https://github.com/williamboman/mason.nvim.git" }
- end)
- assert.spy(ctx.spawn.git).was_called(1)
- assert.spy(ctx.spawn.git).was_called_with {
- "clone",
- "--depth",
- "1",
- vim.NIL,
- "https://github.com/williamboman/mason.nvim.git",
- ".",
- }
- end)
- )
-
- it(
- "should fetch and checkout revision if requested",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "1337" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, function()
- git.clone { "https://github.com/williamboman/mason.nvim.git" }
- end)
- assert.spy(ctx.spawn.git).was_called(3)
- assert.spy(ctx.spawn.git).was_called_with {
- "clone",
- "--depth",
- "1",
- vim.NIL,
- "https://github.com/williamboman/mason.nvim.git",
- ".",
- }
- assert.spy(ctx.spawn.git).was_called_with {
- "fetch",
- "--depth",
- "1",
- "origin",
- "1337",
- }
- assert.spy(ctx.spawn.git).was_called_with { "checkout", "FETCH_HEAD" }
- end)
- )
-
- it(
- "should provide receipt information",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle)
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, function()
- git.clone({ "https://github.com/williamboman/mason.nvim.git" }).with_receipt()
- end)
- assert.same({
- type = "git",
- remote = "https://github.com/williamboman/mason.nvim.git",
- }, ctx.receipt.primary_source)
- assert.is_true(#ctx.receipt.secondary_sources == 0)
- end)
- )
-end)
-
-describe("git version check", function()
- it(
- "should return current version",
- async_test(function()
- stub(spawn, "git")
- spawn.git.returns(Result.success {
- stdout = [[19c668c]],
- })
-
- local result = git.get_installed_revision({ type = "git" }, "/tmp/install/dir")
-
- assert.spy(spawn.git).was_called(1)
- assert.spy(spawn.git).was_called_with { "rev-parse", "--short", "HEAD", cwd = "/tmp/install/dir" }
- assert.is_true(result:is_success())
- assert.equals("19c668c", result:get_or_nil())
- end)
- )
-
- it(
- "should check for outdated git clone",
- async_test(function()
- stub(spawn, "git")
- spawn.git.returns(Result.success {
- stdout = _.dedent [[
- 728307a74cd5f2dec7ca2ca164785c25673d6328
- 19c668cd10695b243b09452f0dfd53570c1a2e7d
- ]],
- })
-
- local result = git.check_outdated_git_clone(
- mock.new {
- primary_source = mock.new {
- type = "git",
- remote = "https://github.com/williamboman/mason.nvim.git",
- },
- },
- "/tmp/install/dir"
- )
-
- assert.spy(spawn.git).was_called(2)
- assert.spy(spawn.git).was_called_with {
- "fetch",
- "origin",
- "HEAD",
- cwd = "/tmp/install/dir",
- }
- assert.spy(spawn.git).was_called_with {
- "rev-parse",
- "FETCH_HEAD",
- "HEAD",
- cwd = "/tmp/install/dir",
- }
- assert.is_true(result:is_success())
- assert.same({
- name = "https://github.com/williamboman/mason.nvim.git",
- current_version = "19c668cd10695b243b09452f0dfd53570c1a2e7d",
- latest_version = "728307a74cd5f2dec7ca2ca164785c25673d6328",
- }, result:get_or_nil())
- end)
- )
-
- it(
- "should return failure if clone is not outdated",
- async_test(function()
- stub(spawn, "git")
- spawn.git.returns(Result.success {
- stdout = _.dedent [[
- 19c668cd10695b243b09452f0dfd53570c1a2e7d
- 19c668cd10695b243b09452f0dfd53570c1a2e7d
- ]],
- })
-
- local result = git.check_outdated_git_clone(
- mock.new {
- primary_source = mock.new {
- type = "git",
- remote = "https://github.com/williamboman/mason.nvim.git",
- },
- },
- "/tmp/install/dir"
- )
-
- assert.is_true(result:is_failure())
- assert.equals("Git clone is up to date.", result:err_or_nil())
- end)
- )
-end)
diff --git a/tests/mason-core/managers/github_client_spec.lua b/tests/mason-core/managers/github_client_spec.lua
deleted file mode 100644
index d07a0e74..00000000
--- a/tests/mason-core/managers/github_client_spec.lua
+++ /dev/null
@@ -1,23 +0,0 @@
-local Result = require "mason-core.result"
-local client = require "mason-core.managers.github.client"
-local spawn = require "mason-core.spawn"
-local stub = require "luassert.stub"
-
-describe("github client", function()
- it("should provide query parameters in api calls", function()
- stub(spawn, "gh")
- spawn.gh.returns(Result.success { stdout = "response data" })
- client.api_call("repos/some/repo", {
- params = {
- page = 23,
- page_limit = 82,
- },
- })
- assert.spy(spawn.gh).was_called(1)
- assert.spy(spawn.gh).was_called_with {
- "api",
- "repos/some/repo?page=23&page_limit=82",
- env = { CLICOLOR_FORCE = 0 },
- }
- end)
-end)
diff --git a/tests/mason-core/managers/github_spec.lua b/tests/mason-core/managers/github_spec.lua
deleted file mode 100644
index 852c3ff6..00000000
--- a/tests/mason-core/managers/github_spec.lua
+++ /dev/null
@@ -1,103 +0,0 @@
-local mock = require "luassert.mock"
-local stub = require "luassert.stub"
-
-local Optional = require "mason-core.optional"
-local Result = require "mason-core.result"
-local github = require "mason-core.managers.github"
-local installer = require "mason-core.installer"
-local providers = require "mason-core.providers"
-
-describe("github release file", function()
- it(
- "should use provided version",
- async_test(function()
- stub(providers.github, "get_latest_release")
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle)
- installer.prepare_installer(ctx):get_or_throw()
- local source = installer.exec_in_context(ctx, function()
- return github.release_file {
- repo = "williamboman/mason.nvim",
- asset_file = "program.exe",
- version = Optional.of "13.37",
- }
- end)
- assert.spy(providers.github.get_latest_release).was_not_called()
- assert.equals("13.37", source.release)
- assert.equals(
- "https://github.com/williamboman/mason.nvim/releases/download/13.37/program.exe",
- source.download_url
- )
- end)
- )
-
- it(
- "should use use dynamic asset_file",
- async_test(function()
- stub(providers.github, "get_latest_release")
- providers.github.get_latest_release.returns(Result.success(mock.new {
- tag_name = "im_the_tag",
- }))
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle)
- installer.prepare_installer(ctx):get_or_throw()
- local source = installer.exec_in_context(ctx, function()
- return github.release_file {
- repo = "williamboman/mason.nvim",
- asset_file = function(version)
- return version .. "_for_reals"
- end,
- }
- end)
- assert.spy(providers.github.get_latest_release).was_called(1)
- assert.spy(providers.github.get_latest_release).was_called_with "williamboman/mason.nvim"
- assert.equals("im_the_tag", source.release)
- assert.equals("im_the_tag_for_reals", source.asset_file)
- assert.equals(
- "https://github.com/williamboman/mason.nvim/releases/download/im_the_tag/im_the_tag_for_reals",
- source.download_url
- )
- end)
- )
-end)
-
-describe("github release version", function()
- it(
- "should use provided version",
- async_test(function()
- stub(providers.github, "get_latest_release")
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle)
- installer.prepare_installer(ctx):get_or_throw()
- local source = installer.exec_in_context(ctx, function()
- return github.release_version {
- repo = "williamboman/mason.nvim",
- version = Optional.of "13.37",
- }
- end)
- assert.spy(providers.github.get_latest_release).was_not_called()
- assert.equals("13.37", source.release)
- end)
- )
-
- it(
- "should fetch latest release from GitHub API",
- async_test(function()
- async_test(function()
- stub(providers.github, "get_latest_release")
- providers.github.get_latest_release.returns(Result.success { tag_name = "v42" })
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle)
- installer.prepare_installer(ctx):get_or_throw()
- local source = installer.exec_in_context(ctx, function()
- return github.release_version {
- repo = "williamboman/mason.nvim",
- }
- end)
- assert.spy(providers.github.get_latest_release).was_called(1)
- assert.spy(providers.github.get_latest_release).was_called_with "williamboman/mason.nvim"
- assert.equals("v42", source.release)
- end)
- end)
- )
-end)
diff --git a/tests/mason-core/managers/go_spec.lua b/tests/mason-core/managers/go_spec.lua
deleted file mode 100644
index fd3ca043..00000000
--- a/tests/mason-core/managers/go_spec.lua
+++ /dev/null
@@ -1,171 +0,0 @@
-local Result = require "mason-core.result"
-local go = require "mason-core.managers.go"
-local installer = require "mason-core.installer"
-local mock = require "luassert.mock"
-local path = require "mason-core.path"
-local spawn = require "mason-core.spawn"
-local spy = require "luassert.spy"
-local stub = require "luassert.stub"
-
-describe("go manager", function()
- it(
- "should call go install",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, go.packages { "main-package", "supporting-package", "supporting-package2" })
- assert.spy(ctx.spawn.go).was_called(3)
- assert.spy(ctx.spawn.go).was_called_with {
- "install",
- "-v",
- "main-package@42.13.37",
- env = { GOBIN = path.package_build_prefix "dummy" },
- }
- assert.spy(ctx.spawn.go).was_called_with {
- "install",
- "-v",
- "supporting-package@latest",
- env = { GOBIN = path.package_build_prefix "dummy" },
- }
- assert.spy(ctx.spawn.go).was_called_with {
- "install",
- "-v",
- "supporting-package2@latest",
- env = { GOBIN = path.package_build_prefix "dummy" },
- }
- end)
- )
-
- it(
- "should provide receipt information",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, go.packages { "main-package", "supporting-package", "supporting-package2" })
- assert.same({
- type = "go",
- package = "main-package",
- }, ctx.receipt.primary_source)
- assert.same({
- {
- type = "go",
- package = "supporting-package",
- },
- {
- type = "go",
- package = "supporting-package2",
- },
- }, ctx.receipt.secondary_sources)
- end)
- )
-end)
-
-describe("go version check", function()
- local go_version_output = [[
-gopls: go1.18
- path golang.org/x/tools/cmd
- mod golang.org/x/tools/cmd v0.8.1 h1:q5nDpRopYrnF4DN/1o8ZQ7Oar4Yd4I5OtGMx5RyV2/8=
- dep github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
- dep mvdan.cc/xurls/v2 v2.4.0 h1:tzxjVAj+wSBmDcF6zBB7/myTy3gX9xvi8Tyr28AuQgc=
- build -compiler=gc
- build GOOS=darwin
-]]
-
- it("should parse go version output", function()
- local parsed = go.parse_mod_version_output(go_version_output)
- assert.same({
- path = { ["golang.org/x/tools/cmd"] = "" },
- mod = { ["golang.org/x/tools/cmd"] = "v0.8.1" },
- dep = { ["github.com/google/go-cmp"] = "v0.5.7", ["mvdan.cc/xurls/v2"] = "v2.4.0" },
- build = { ["-compiler=gc"] = "", ["GOOS=darwin"] = "" },
- }, parsed)
- end)
-
- it(
- "should return current version",
- async_test(function()
- stub(spawn, "go")
- spawn.go.returns(Result.success { stdout = go_version_output })
-
- local result = go.get_installed_primary_package_version(
- mock.new {
- primary_source = mock.new {
- type = "go",
- package = "golang.org/x/tools/cmd/gopls/...",
- },
- },
- path.package_prefix "dummy"
- )
-
- assert.spy(spawn.go).was_called(1)
- assert.spy(spawn.go).was_called_with {
- "version",
- "-m",
- "gopls",
- cwd = path.package_prefix "dummy",
- }
- assert.is_true(result:is_success())
- assert.equals("v0.8.1", result:get_or_nil())
- end)
- )
-
- it(
- "should return outdated primary package",
- async_test(function()
- stub(spawn, "go")
- spawn.go
- .on_call_with({
- "list",
- "-json",
- "-m",
- "golang.org/x/tools/cmd@latest",
- cwd = path.package_prefix "dummy",
- })
- .returns(Result.success {
- stdout = ([[
- {
- "Path": %q,
- "Version": "v2.0.0"
- }
- ]]):format(path.package_prefix "dummy"),
- })
- spawn.go
- .on_call_with({
- "version",
- "-m",
- "gopls",
- cwd = path.package_prefix "dummy",
- })
- .returns(Result.success {
- stdout = go_version_output,
- })
-
- local result = go.check_outdated_primary_package(
- mock.new {
- primary_source = mock.new {
- type = "go",
- package = "golang.org/x/tools/cmd/gopls/...",
- },
- },
- path.package_prefix "dummy"
- )
-
- assert.is_true(result:is_success())
- assert.same({
- name = "golang.org/x/tools/cmd",
- current_version = "v0.8.1",
- latest_version = "v2.0.0",
- }, result:get_or_nil())
- end)
- )
-
- it("should parse package mod names", function()
- assert.equals("github.com/cweill/gotests", go.parse_package_mod "github.com/cweill/gotests/...")
- assert.equals("golang.org/x/tools/gopls", go.parse_package_mod "golang.org/x/tools/gopls/...")
- assert.equals("golang.org/x/crypto", go.parse_package_mod "golang.org/x/crypto/...")
- assert.equals("github.com/go-delve/delve", go.parse_package_mod "github.com/go-delve/delve/cmd/dlv")
- assert.equals("mvdan.cc/sh/v3", go.parse_package_mod "mvdan.cc/sh/v3/cmd/shfmt")
- end)
-end)
diff --git a/tests/mason-core/managers/luarocks_spec.lua b/tests/mason-core/managers/luarocks_spec.lua
deleted file mode 100644
index d89f65fa..00000000
--- a/tests/mason-core/managers/luarocks_spec.lua
+++ /dev/null
@@ -1,139 +0,0 @@
-local a = require "mason-core.async"
-local installer = require "mason-core.installer"
-local luarocks = require "mason-core.managers.luarocks"
-local path = require "mason-core.path"
-
-describe("luarocks manager", function()
- before_each(function()
- a.run_blocking(installer.create_prefix_dirs)
- end)
-
- it(
- "should install provided package",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle)
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, luarocks.package "lua-cjson")
- assert.spy(ctx.spawn.luarocks).was_called(1)
- assert.spy(ctx.spawn.luarocks).was_called_with {
- "install",
- "--tree",
- path.package_prefix "dummy",
- vim.NIL, -- --dev flag
- vim.NIL, -- --server flag
- "lua-cjson",
- vim.NIL, -- version
- }
- end)
- )
-
- it(
- "should install provided version",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "1.2.3" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, luarocks.package "lua-cjson")
- assert.spy(ctx.spawn.luarocks).was_called(1)
- assert.spy(ctx.spawn.luarocks).was_called_with {
- "install",
- "--tree",
- path.package_prefix "dummy",
- vim.NIL, -- --dev flag
- vim.NIL, -- --server flag
- "lua-cjson",
- "1.2.3",
- }
- end)
- )
-
- it(
- "should provide --dev flag",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle)
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, luarocks.package("lua-cjson", { dev = true }))
- assert.spy(ctx.spawn.luarocks).was_called(1)
- assert.spy(ctx.spawn.luarocks).was_called_with {
- "install",
- "--tree",
- path.package_prefix "dummy",
- "--dev",
- vim.NIL, -- --server flag
- "lua-cjson",
- vim.NIL, -- version
- }
- end)
- )
-
- it(
- "should provide --server flag",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle)
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, luarocks.package("luaformatter", { server = "https://luarocks.org/dev" }))
- assert.spy(ctx.spawn.luarocks).was_called(1)
- assert.spy(ctx.spawn.luarocks).was_called_with {
- "install",
- "--tree",
- path.package_prefix "dummy",
- vim.NIL, -- --dev flag
- "--server=https://luarocks.org/dev",
- "luaformatter",
- vim.NIL, -- version
- }
- end)
- )
-
- it("should parse outdated luarocks", function()
- assert.same(
- {
- {
- name = "lua-cjson",
- installed = "2.1.0-1",
- available = "2.1.0.6-1",
- repo = "https://luarocks.org",
- },
- {
- name = "lua-resty-influx-mufanh",
- installed = "0.2.1-0",
- available = "0.2.1-1",
- repo = "https://luarocks.org",
- },
- },
- luarocks.parse_outdated_rocks [[lua-cjson 2.1.0-1 2.1.0.6-1 https://luarocks.org
-lua-resty-influx-mufanh 0.2.1-0 0.2.1-1 https://luarocks.org]]
- )
- end)
-
- it("should parse listed luarocks", function()
- assert.same(
- {
- {
- package = "lua-cjson",
- version = "2.1.0-1",
- arch = "installed",
- nrepo = "/my/luarock/loc",
- },
- {
- package = "lua-resty-http",
- version = "0.17.0.beta.1-0",
- arch = "installed",
- nrepo = "/my/luarock/loc",
- },
- {
- package = "lua-resty-influx-mufanh",
- version = "0.2.1-0",
- arch = "installed",
- nrepo = "/my/luarock/loc",
- },
- },
- luarocks.parse_installed_rocks [[lua-cjson 2.1.0-1 installed /my/luarock/loc
-lua-resty-http 0.17.0.beta.1-0 installed /my/luarock/loc
-lua-resty-influx-mufanh 0.2.1-0 installed /my/luarock/loc]]
- )
- end)
-end)
diff --git a/tests/mason-core/managers/npm_spec.lua b/tests/mason-core/managers/npm_spec.lua
deleted file mode 100644
index 31500ac7..00000000
--- a/tests/mason-core/managers/npm_spec.lua
+++ /dev/null
@@ -1,206 +0,0 @@
-local Result = require "mason-core.result"
-local api = require "mason-registry.api"
-local installer = require "mason-core.installer"
-local match = require "luassert.match"
-local mock = require "luassert.mock"
-local npm = require "mason-core.managers.npm"
-local path = require "mason-core.path"
-local spawn = require "mason-core.spawn"
-local spy = require "luassert.spy"
-local stub = require "luassert.stub"
-
-describe("npm manager", function()
- it(
- "should call npm install",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, npm.packages { "main-package", "supporting-package", "supporting-package2" })
- assert.spy(ctx.spawn.npm).was_called_with(match.tbl_containing {
- "install",
- match.tbl_containing {
- "main-package@42.13.37",
- "supporting-package",
- "supporting-package2",
- },
- })
- end)
- )
-
- it(
- "should call npm init if node_modules and package.json doesnt exist",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle)
- ctx.fs.file_exists = mockx.returns(false)
- ctx.fs.dir_exists = mockx.returns(false)
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, function()
- npm.install { "main-package", "supporting-package", "supporting-package2" }
- end)
- assert.spy(ctx.spawn.npm).was_called_with {
- "init",
- "--yes",
- "--scope=mason",
- }
- end)
- )
-
- it(
- "should append .npmrc file",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- ctx.fs.append_file = spy.new(mockx.just_runs())
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, npm.packages { "main-package", "supporting-package", "supporting-package2" })
- assert.spy(ctx.fs.append_file).was_called(1)
- assert.spy(ctx.fs.append_file).was_called_with(ctx.fs, ".npmrc", "global-style=true")
- end)
- )
-
- it(
- "should provide receipt information",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, npm.packages { "main-package", "supporting-package", "supporting-package2" })
- assert.same({
- type = "npm",
- package = "main-package",
- }, ctx.receipt.primary_source)
- assert.same({
- {
- type = "npm",
- package = "supporting-package",
- },
- {
- type = "npm",
- package = "supporting-package2",
- },
- }, ctx.receipt.secondary_sources)
- end)
- )
-end)
-
-describe("npm version check", function()
- it(
- "should return current version",
- async_test(function()
- stub(spawn, "npm", function()
- return Result.success {
- stdout = [[
- {
- "name": "bash",
- "dependencies": {
- "bash-language-server": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/bash-language-server/-/bash-language-server-2.0.0.tgz"
- }
- }
- }
- ]],
- }
- end)
-
- local result = npm.get_installed_primary_package_version(
- mock.new {
- primary_source = mock.new {
- type = "npm",
- package = "bash-language-server",
- },
- },
- path.package_prefix "dummy"
- )
-
- assert.spy(spawn.npm).was_called(1)
- assert.spy(spawn.npm).was_called_with { "ls", "--json", cwd = path.package_prefix "dummy" }
- assert.is_true(result:is_success())
- assert.equals("2.0.0", result:get_or_nil())
- end)
- )
-
- it(
- "should return outdated primary package",
- async_test(function()
- stub(api, "get")
- api.get.on_call_with("/api/npm/bash-language-server/versions/latest").returns(Result.success {
- name = "bash-language-server",
- version = "2.0.0",
- })
- stub(spawn, "npm", function()
- return Result.success {
- stdout = [[
- {
- "name": "bash",
- "dependencies": {
- "bash-language-server": {
- "version": "1.17.0",
- "resolved": "https://registry.npmjs.org/bash-language-server/-/bash-language-server-1.17.0.tgz"
- }
- }
- }
- ]],
- }
- end)
-
- local result = npm.check_outdated_primary_package(
- mock.new {
- primary_source = mock.new {
- type = "npm",
- package = "bash-language-server",
- },
- },
- path.package_prefix "dummy"
- )
-
- assert.is_true(result:is_success())
- assert.same({
- name = "bash-language-server",
- current_version = "1.17.0",
- latest_version = "2.0.0",
- }, result:get_or_nil())
- end)
- )
-
- it(
- "should return failure if primary package is not outdated",
- async_test(function()
- stub(spawn, "npm", function()
- return Result.success {
- stdout = [[
- {
- "name": "bash",
- "dependencies": {
- "bash-language-server": {
- "version": "1.17.0",
- "resolved": "https://registry.npmjs.org/bash-language-server/-/bash-language-server-1.17.0.tgz"
- }
- }
- }
- ]],
- }
- end)
- stub(api, "get")
- api.get.on_call_with("/api/npm/bash-language-server/versions/latest").returns(Result.success {
- name = "bash-language-server",
- version = "1.17.0",
- })
-
- local result = npm.check_outdated_primary_package(
- mock.new {
- primary_source = mock.new {
- type = "npm",
- package = "bash-language-server",
- },
- },
- path.package_prefix "dummy"
- )
-
- assert.is_true(result:is_failure())
- assert.equals("Primary package is not outdated.", result:err_or_nil())
- end)
- )
-end)
diff --git a/tests/mason-core/managers/opam_spec.lua b/tests/mason-core/managers/opam_spec.lua
deleted file mode 100644
index 297f9d8b..00000000
--- a/tests/mason-core/managers/opam_spec.lua
+++ /dev/null
@@ -1,57 +0,0 @@
-local installer = require "mason-core.installer"
-local match = require "luassert.match"
-local opam = require "mason-core.managers.opam"
-
-describe("opam manager", function()
- it(
- "should call opam install",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(
- ctx,
- opam.packages { "main-package", "supporting-package", "supporting-package2" }
- )
- assert.spy(ctx.spawn.opam).was_called(1)
- assert.spy(ctx.spawn.opam).was_called_with(match.tbl_containing {
- "install",
- "--destdir=.",
- "--yes",
- "--verbose",
- match.tbl_containing {
- "main-package.42.13.37",
- "supporting-package",
- "supporting-package2",
- },
- })
- end)
- )
-
- it(
- "should provide receipt information",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(
- ctx,
- opam.packages { "main-package", "supporting-package", "supporting-package2" }
- )
- assert.same({
- type = "opam",
- package = "main-package",
- }, ctx.receipt.primary_source)
- assert.same({
- {
- type = "opam",
- package = "supporting-package",
- },
- {
- type = "opam",
- package = "supporting-package2",
- },
- }, ctx.receipt.secondary_sources)
- end)
- )
-end)
diff --git a/tests/mason-core/managers/pip3_spec.lua b/tests/mason-core/managers/pip3_spec.lua
deleted file mode 100644
index 9ad8e1d8..00000000
--- a/tests/mason-core/managers/pip3_spec.lua
+++ /dev/null
@@ -1,284 +0,0 @@
-local mock = require "luassert.mock"
-local path = require "mason-core.path"
-local spy = require "luassert.spy"
-local stub = require "luassert.stub"
-
-local Result = require "mason-core.result"
-local _ = require "mason-core.functional"
-local a = require "mason-core.async"
-local api = require "mason-registry.api"
-local installer = require "mason-core.installer"
-local pip3 = require "mason-core.managers.pip3"
-local settings = require "mason.settings"
-local spawn = require "mason-core.spawn"
-
-describe("pip3 manager", function()
- before_each(function()
- settings.set(settings._DEFAULT_SETTINGS)
- a.run_blocking(installer.create_prefix_dirs)
- end)
-
- it("normalizes pip3 packages", function()
- local normalize = pip3.normalize_package
- assert.equals("python-lsp-server", normalize "python-lsp-server[all]")
- assert.equals("python-lsp-server", normalize "python-lsp-server[]")
- assert.equals("python-lsp-server", normalize "python-lsp-server[[]]")
- end)
-
- it(
- "should create venv and call pip3 install",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(
- ctx,
- pip3.packages { "main-package", "supporting-package", "supporting-package2" }
- )
- assert.equals(path.package_prefix "dummy", ctx.cwd:get()) -- should've promoted cwd
- assert.spy(ctx.spawn.python3).was_called(1)
- assert.spy(ctx.spawn.python3).was_called_with {
- "-m",
- "venv",
- "venv",
- }
- assert.spy(ctx.spawn.python).was_called(1)
- assert.spy(ctx.spawn.python).was_called_with {
- "-m",
- "pip",
- "--disable-pip-version-check",
- "install",
- "-U",
- {},
- {
- "main-package==42.13.37",
- "supporting-package",
- "supporting-package2",
- },
- with_paths = { path.concat { path.package_prefix "dummy", "venv", "bin" } },
- }
- end)
- )
-
- it(
- "should exhaust python3 executable candidates if all fail",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle)
- ctx.spawn.python3 = spy.new(mockx.throws())
- ctx.spawn.python = spy.new(mockx.throws())
- local err = assert.has_error(function()
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, pip3.packages { "package" })
- end)
-
- assert.equals("Unable to create python3 venv environment.", err)
- assert.spy(ctx.spawn.python3).was_called(1)
- assert.spy(ctx.spawn.python).was_called(1)
- end)
- )
-
- it(
- "should use install_args from settings",
- async_test(function()
- settings.set {
- pip = {
- install_args = { "--proxy", "http://localhost:8080" },
- },
- }
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle)
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, pip3.packages { "package" })
- assert.spy(ctx.spawn.python).was_called(1)
- assert.spy(ctx.spawn.python).was_called_with {
- "-m",
- "pip",
- "--disable-pip-version-check",
- "install",
- "-U",
- { "--proxy", "http://localhost:8080" },
- { "package" },
- with_paths = { path.concat { path.package_prefix "dummy", "venv", "bin" } },
- }
- end)
- )
-
- it(
- "should upgrade pip",
- async_test(function()
- settings.set {
- pip = {
- upgrade_pip = true,
- },
- }
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle)
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(ctx, pip3.packages { "package" })
- assert.spy(ctx.spawn.python).was_called(2)
- assert.spy(ctx.spawn.python).was_called_with {
- "-m",
- "pip",
- "--disable-pip-version-check",
- "install",
- "-U",
- {},
- "pip",
- with_paths = { path.concat { path.package_prefix "dummy", "venv", "bin" } },
- }
- assert.spy(ctx.spawn.python).was_called_with {
- "-m",
- "pip",
- "--disable-pip-version-check",
- "install",
- "-U",
- {},
- { "package" },
- with_paths = { path.concat { path.package_prefix "dummy", "venv", "bin" } },
- }
- end)
- )
-
- it(
- "should provide receipt information",
- async_test(function()
- local handle = InstallHandleGenerator "dummy"
- local ctx = InstallContextGenerator(handle, { version = "42.13.37" })
- installer.prepare_installer(ctx):get_or_throw()
- installer.exec_in_context(
- ctx,
- pip3.packages { "main-package", "supporting-package", "supporting-package2" }
- )
- assert.same({
- type = "pip3",
- package = "main-package",
- }, ctx.receipt.primary_source)
- assert.same({
- {
- type = "pip3",
- package = "supporting-package",
- },
- {
- type = "pip3",
- package = "supporting-package2",
- },
- }, ctx.receipt.secondary_sources)
- end)
- )
-end)
-
-describe("pip3 version check", function()
- it(
- "should return current version",
- async_test(function()
- stub(spawn, "python")
- spawn.python.returns(Result.success {
- stdout = _.dedent [[
- [
- {"name": "astroid", "version": "2.9.3"},
- {"name": "mccabe", "version": "0.6.1"},
- {"name": "python-lsp-server", "version": "1.3.0", "latest_version": "1.4.0", "latest_filetype": "wheel"},
- {"name": "wrapt", "version": "1.13.3", "latest_version": "1.14.0", "latest_filetype": "wheel"}
- ]
- ]],
- })
-
- local result = pip3.get_installed_primary_package_version(
- mock.new {
- primary_source = mock.new {
- type = "pip3",
- package = "python-lsp-server",
- },
- },
- path.package_prefix "dummy"
- )
-
- assert.spy(spawn.python).was_called(1)
- assert.spy(spawn.python).was_called_with {
- "-m",
- "pip",
- "list",
- "--format=json",
- cwd = path.package_prefix "dummy",
- with_paths = { path.concat { path.package_prefix "dummy", "venv", "bin" } },
- }
- assert.is_true(result:is_success())
- assert.equals("1.3.0", result:get_or_nil())
- end)
- )
-
- it(
- "should return outdated primary package",
- async_test(function()
- stub(api, "get")
- api.get.on_call_with("/api/pypi/python-lsp-server/versions/latest").returns(Result.success {
- name = "python-lsp-server",
- version = "1.4.0",
- })
- stub(spawn, "python")
- spawn.python.returns(Result.success {
- stdout = [[
- [
- {"name": "astroid", "version": "2.9.3"},
- {"name": "mccabe", "version": "0.6.1"},
- {"name": "python-lsp-server", "version": "1.3.0", "latest_version": "1.4.0", "latest_filetype": "wheel"},
- {"name": "wrapt", "version": "1.13.3", "latest_version": "1.14.0", "latest_filetype": "wheel"}
- ]
- ]],
- })
-
- local result = pip3.check_outdated_primary_package(
- mock.new {
- primary_source = mock.new {
- type = "pip3",
- package = "python-lsp-server",
- },
- },
- path.package_prefix "dummy"
- )
-
- assert.is_true(result:is_success())
- assert.same({
- name = "python-lsp-server",
- current_version = "1.3.0",
- latest_version = "1.4.0",
- }, result:get_or_nil())
- end)
- )
-
- it(
- "should return failure if primary package is not outdated",
- async_test(function()
- stub(spawn, "python")
- spawn.python.returns(Result.success {
- stdout = [[
- [
- {"name": "astroid", "version": "2.9.3"},
- {"name": "mccabe", "version": "0.6.1"},
- {"name": "python-lsp-server", "version": "1.3.0", "latest_version": "1.4.0", "latest_filetype": "wheel"},
- {"name": "wrapt", "version": "1.13.3", "latest_version": "1.14.0", "latest_filetype": "wheel"}
- ]
- ]],
- })
- stub(api, "get")
- api.get.on_call_with("/api/pypi/python-lsp-server/versions/latest").returns(Result.success {
- name = "python-lsp-server",
- version = "1.3.0",
- })
-
- local result = pip3.check_outdated_primary_package(
- mock.new {
- primary_source = mock.new {
- type = "pip3",
- package = "python-lsp-server",
- },
- },
- "/tmp/install/dir"
- )
-
- assert.is_true(result:is_failure())
- assert.equals("Primary package is not outdated.", result:err_or_nil())
- end)
- )
-end)