feat: added config option for process timeout

This commit is contained in:
Folke Lemaitre 2022-11-30 23:38:45 +01:00
parent f2072f0158
commit bd2d64230f
No known key found for this signature in database
GPG Key ID: 41F8B1FBACAE2040
3 changed files with 44 additions and 12 deletions

View File

@ -25,7 +25,7 @@
- [ ] health checks: check merge conflicts async - [ ] health checks: check merge conflicts async
- [ ] allow setting up plugins through config - [ ] allow setting up plugins through config
- [ ] task timeout - [x] task timeout
- [ ] log file - [ ] log file
- [ ] deal with resourcing init.lua. Check a global? - [ ] deal with resourcing init.lua. Check a global?
- [x] incorrect when switching TN from opt to start - [x] incorrect when switching TN from opt to start

View File

@ -18,6 +18,7 @@ M.defaults = {
-- defaults for `Lazy log` -- defaults for `Lazy log`
-- log = { "-10" }, -- last 10 commits -- log = { "-10" }, -- last 10 commits
log = { "--since=1 days ago" }, -- commits from the last 3 days log = { "--since=1 days ago" }, -- commits from the last 3 days
timeout = 120, -- processes taking over 2 minutes will be killed
}, },
-- Any plugin spec that contains one of the patterns will use your -- Any plugin spec that contains one of the patterns will use your
-- local repo in the projects folder instead of fetchig it from github -- local repo in the projects folder instead of fetchig it from github

View File

@ -1,37 +1,66 @@
local Config = require("lazy.core.config")
local M = {} local M = {}
---@alias ProcessOpts {args: string[], cwd?: string, on_line?:fun(string), on_exit?: fun(ok:boolean, output:string)} ---@diagnostic disable-next-line: no-unknown
local uv = vim.loop
---@class ProcessOpts
---@field args string[]
---@field cwd? string
---@field on_line? fun(string)
---@field on_exit? fun(ok:boolean, output:string)
---@field timeout? number
---@param opts? ProcessOpts
function M.spawn(cmd, opts) function M.spawn(cmd, opts)
opts = opts or {} opts = opts or {}
opts.timeout = opts.timeout or (Config.options.git.timeout * 1000)
local env = { local env = {
"GIT_TERMINAL_PROMPT=0", "GIT_TERMINAL_PROMPT=0",
"GIT_SSH_COMMAND=ssh -oBatchMode=yes", "GIT_SSH_COMMAND=ssh -oBatchMode=yes",
} }
for key, value in for key, value in
pairs(vim.loop.os_environ() --[[@as string[] ]]) pairs(uv.os_environ() --[[@as string[] ]])
do do
table.insert(env, key .. "=" .. value) table.insert(env, key .. "=" .. value)
end end
local stdout = vim.loop.new_pipe() local stdout = uv.new_pipe()
local stderr = vim.loop.new_pipe() local stderr = uv.new_pipe()
local output = "" local output = ""
---@type vim.loop.Process ---@type vim.loop.Process
local handle = nil local handle = nil
handle = vim.loop.spawn(cmd, { local timeout
local killed = false
if opts.timeout then
timeout = uv.new_timer()
timeout:start(opts.timeout, 0, function()
if handle and not handle:is_closing() then
killed = true
uv.process_kill(handle, "sigint")
end
end)
end
handle = uv.spawn(cmd, {
stdio = { nil, stdout, stderr }, stdio = { nil, stdout, stderr },
args = opts.args, args = opts.args,
cwd = opts.cwd, cwd = opts.cwd,
env = env, env = env,
}, function(exit_code) }, function(exit_code, signal)
if timeout then
timeout:stop()
timeout:close()
end
handle:close() handle:close()
stdout:close() stdout:close()
stderr:close() stderr:close()
local check = vim.loop.new_check() local check = uv.new_check()
check:start(function() check:start(function()
if not stdout:is_closing() or not stderr:is_closing() then if not stdout:is_closing() or not stderr:is_closing() then
return return
@ -39,9 +68,12 @@ function M.spawn(cmd, opts)
check:stop() check:stop()
if opts.on_exit then if opts.on_exit then
output = output:gsub("[^\r\n]+\r", "") output = output:gsub("[^\r\n]+\r", "")
if killed then
output = output .. "\n" .. "Process was killed because it reached the timeout"
end
vim.schedule(function() vim.schedule(function()
opts.on_exit(exit_code == 0, output) opts.on_exit(exit_code == 0 and signal == 0, output)
end) end)
end end
end) end)
@ -51,7 +83,6 @@ function M.spawn(cmd, opts)
if opts.on_exit then if opts.on_exit then
opts.on_exit(false, "Failed to spawn process " .. cmd .. " " .. vim.inspect(opts)) opts.on_exit(false, "Failed to spawn process " .. cmd .. " " .. vim.inspect(opts))
end end
return return
end end
@ -71,8 +102,8 @@ function M.spawn(cmd, opts)
end end
end end
vim.loop.read_start(stdout, on_output) uv.read_start(stdout, on_output)
vim.loop.read_start(stderr, on_output) uv.read_start(stderr, on_output)
return handle return handle
end end