aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2023-03-05 02:33:57 +0100
committerGitHub <noreply@github.com>2023-03-05 01:33:57 +0000
commitc1dbd9824ceb03f2e378cc5b732cd11ba0e4c991 (patch)
treefc51d2ede21b745e9810026281fe4fe427f12b8c
parentchore: autogenerate (#1051) (diff)
downloadmason-c1dbd9824ceb03f2e378cc5b732cd11ba0e4c991.tar
mason-c1dbd9824ceb03f2e378cc5b732cd11ba0e4c991.tar.gz
mason-c1dbd9824ceb03f2e378cc5b732cd11ba0e4c991.tar.bz2
mason-c1dbd9824ceb03f2e378cc5b732cd11ba0e4c991.tar.lz
mason-c1dbd9824ceb03f2e378cc5b732cd11ba0e4c991.tar.xz
mason-c1dbd9824ceb03f2e378cc5b732cd11ba0e4c991.tar.zst
mason-c1dbd9824ceb03f2e378cc5b732cd11ba0e4c991.zip
feat(InstallContext): add strict_mode flag (#1055)
Also add some more ctx.fs methods.
-rw-r--r--lua/mason-core/fs.lua7
-rw-r--r--lua/mason-core/installer/context.lua49
-rw-r--r--tests/helpers/lua/test_helpers.lua8
-rw-r--r--tests/mason-core/installer/context_spec.lua1
-rw-r--r--tests/mason-core/installer/installer_spec.lua20
5 files changed, 68 insertions, 17 deletions
diff --git a/lua/mason-core/fs.lua b/lua/mason-core/fs.lua
index b60749e2..e9b7a629 100644
--- a/lua/mason-core/fs.lua
+++ b/lua/mason-core/fs.lua
@@ -146,6 +146,13 @@ local function make_module(uv)
uv.fs_symlink(path, new_path)
end
+ ---@param path string
+ ---@param mode integer
+ function M.chmod(path, mode)
+ log.trace("fs: chmod", path, mode)
+ uv.fs_chmod(path, mode)
+ end
+
return M
end
diff --git a/lua/mason-core/installer/context.lua b/lua/mason-core/installer/context.lua
index 93fe688b..d5c5583b 100644
--- a/lua/mason-core/installer/context.lua
+++ b/lua/mason-core/installer/context.lua
@@ -8,17 +8,22 @@ local Optional = require "mason-core.optional"
local _ = require "mason-core.functional"
---@class ContextualSpawn
+---@field strict_mode boolean Whether spawn failures should raise an exception rather then return a Result.
---@field cwd CwdManager
---@field handle InstallHandle
+---@field [string] async fun(opts: SpawnArgs): Result
local ContextualSpawn = {}
---@param cwd CwdManager
---@param handle InstallHandle
-function ContextualSpawn.new(cwd, handle)
- return setmetatable({ cwd = cwd, handle = handle }, ContextualSpawn)
+---@param strict_mode boolean
+function ContextualSpawn.new(cwd, handle, strict_mode)
+ return setmetatable({ cwd = cwd, handle = handle, strict_mode = strict_mode }, ContextualSpawn)
end
-function ContextualSpawn.__index(self, cmd)
+---@param cmd string
+function ContextualSpawn:__index(cmd)
+ ---@param args JobSpawnOpts
return function(args)
args.cwd = args.cwd or self.cwd:get()
args.stdio_sink = args.stdio_sink or self.handle.stdio.sink
@@ -36,9 +41,12 @@ function ContextualSpawn.__index(self, cmd)
self.handle:deregister_spawn_handle(captured_handle)
end
end
- -- We get_or_throw() here for convenience reasons.
- -- Almost every time spawn is called via context we want the command to succeed.
- return spawn[cmd](args):on_success(pop_spawn_stack):on_failure(pop_spawn_stack):get_or_throw()
+ local result = spawn[cmd](args):on_success(pop_spawn_stack):on_failure(pop_spawn_stack)
+ if self.strict_mode then
+ return result:get_or_throw()
+ else
+ return result
+ end
end
end
@@ -104,9 +112,22 @@ function ContextualFs:rename(old_path, new_path)
end
---@async
----@param dirpath string
-function ContextualFs:mkdir(dirpath)
- return fs.async.mkdir(path.concat { self.cwd:get(), dirpath })
+---@param dir_path string
+function ContextualFs:mkdir(dir_path)
+ return fs.async.mkdir(path.concat { self.cwd:get(), dir_path })
+end
+
+---@async
+---@param file_path string
+---@param mode integer
+function ContextualFs:chmod(file_path, mode)
+ return fs.async.chmod(path.concat { self.cwd:get(), file_path }, mode)
+end
+
+---@async
+---@param file_path string
+function ContextualFs:fstat(file_path)
+ return fs.async.fstat(path.concat { self.cwd:get(), file_path })
end
---@class CwdManager
@@ -142,7 +163,7 @@ end
---@field public receipt InstallReceiptBuilder
---@field public requested_version Optional
---@field public fs ContextualFs
----@field public spawn JobSpawn
+---@field public spawn ContextualSpawn
---@field public handle InstallHandle
---@field public package Package
---@field public cwd CwdManager
@@ -158,7 +179,7 @@ function InstallContext.new(handle, opts)
local cwd_manager = CwdManager.new(path.install_prefix())
return setmetatable({
cwd = cwd_manager,
- spawn = ContextualSpawn.new(cwd_manager, handle),
+ spawn = ContextualSpawn.new(cwd_manager, handle, handle.package.spec.schema ~= "registry+v1"),
handle = handle,
package = handle.package, -- for convenience
fs = ContextualFs.new(cwd_manager),
@@ -246,7 +267,11 @@ end
function InstallContext:write_pyvenv_exec_wrapper(new_executable_rel_path, module)
local pip3 = require "mason-core.managers.pip3"
local module_exists, module_err = pcall(function()
- self.spawn.python { "-c", ("import %s"):format(module), with_paths = { pip3.venv_path(self.cwd:get()) } }
+ local result =
+ self.spawn.python { "-c", ("import %s"):format(module), with_paths = { pip3.venv_path(self.cwd:get()) } }
+ if self.spawn.strict_mode then
+ result:get_or_throw()
+ end
end)
if not module_exists then
log.fmt_error("Failed to find module %q for package %q. %s", module, self.package, module_err)
diff --git a/tests/helpers/lua/test_helpers.lua b/tests/helpers/lua/test_helpers.lua
index 17ec5ae5..08a0e91b 100644
--- a/tests/helpers/lua/test_helpers.lua
+++ b/tests/helpers/lua/test_helpers.lua
@@ -43,10 +43,10 @@ end
---@param opts PackageInstallOpts?
function InstallContextGenerator(handle, opts)
local context = InstallContext.new(handle, opts or {})
- context.spawn = setmetatable({}, {
- __index = function(s, cmd)
- s[cmd] = spy.new(mockx.just_runs())
- return s[cmd]
+ context.spawn = setmetatable({ strict_mode = false }, {
+ __index = function(self, cmd)
+ self[cmd] = spy.new(mockx.just_runs())
+ return self[cmd]
end,
})
return context
diff --git a/tests/mason-core/installer/context_spec.lua b/tests/mason-core/installer/context_spec.lua
index 0a5b7410..e09ebd52 100644
--- a/tests/mason-core/installer/context_spec.lua
+++ b/tests/mason-core/installer/context_spec.lua
@@ -105,7 +105,6 @@ cmd.exe /C echo %GREETING% %*]]
stub(ctx.cwd, "get")
ctx.cwd.get.returns "/tmp/placeholder"
stub(ctx, "write_shell_exec_wrapper")
- stub(ctx.spawn, "python")
ctx:write_pyvenv_exec_wrapper("my-wrapper-script", "my-module")
diff --git a/tests/mason-core/installer/installer_spec.lua b/tests/mason-core/installer/installer_spec.lua
index 094129f9..66cdb89b 100644
--- a/tests/mason-core/installer/installer_spec.lua
+++ b/tests/mason-core/installer/installer_spec.lua
@@ -4,6 +4,7 @@ local stub = require "luassert.stub"
local fs = require "mason-core.fs"
local a = require "mason-core.async"
local path = require "mason-core.path"
+local Result = require "mason-core.result"
local installer = require "mason-core.installer"
local InstallContext = require "mason-core.installer.context"
@@ -147,4 +148,23 @@ describe("installer", function()
.was_called_with(path.package_prefix "dummy/mason-debug.log", "Hello stdout!\nHello stderr!")
end)
)
+
+ it(
+ "should raise spawn errors in strict mode",
+ async_test(function()
+ local handle = InstallHandleGenerator "dummy"
+ stub(handle.package.spec, "install", function(ctx)
+ ctx.spawn.bash { "-c", "exit 42" }
+ end)
+ local result = installer.execute(handle, { debug = true })
+ assert.same(
+ Result.failure {
+ exit_code = 42,
+ signal = 0,
+ },
+ result
+ )
+ assert.equals("spawn: bash failed with exit code 42 and signal 0. ", tostring(result:err_or_nil()))
+ end)
+ )
end)