261021.1 · 5beb1bf72b0810da6ccee50f6087c2f005aeb737
fix(spawn): never delete cwd when tempname() fails
`vim_tempname()` returns NULL when Neovim cannot create its tempdir (e.g. disk full), which Lua converts to an empty string. `fnamemodify("", ":h")` then yields "." and the cleanup `vim.fn.delete(tmpdir, "rf")` recursively wiped the current working directory.
Skip the cleanup when `tempname()` is empty. Successful tempnames are always absolute (`vim_settempdir()` expands them), so only the empty string needs guarding. Add a regression test that runs `spawn.lua` with a stubbed empty `tempname()`, feeds it a valid serialized spec, and asserts both a clean exit and that a sentinel file in the cwd survives.
Fixes #2838
reading declarations
Changes to tests/spawn_spec.lua. All files
@@ -0,0 +1,42 @@+local helpers = require("fzf-lua.test.helpers")+local assert = helpers.assert+local libuv = require("fzf-lua.libuv")+local eq = assert.are.equal++describe("Testing spawn.lua", function()+ it("does not delete the cwd when tempname() fails (#2838)", function()+ ---@diagnostic disable-next-line: deprecated+ local _info = debug.getinfo(1, "S")+ ---@cast _info {source: string}+ -- must be absolute: the child runs with `cwd` set to a temp directory+ local root = vim.fn.fnamemodify(_info.source:gsub("^@", ""), ":p:h:h")+ local script = (root .. "/lua/fzf-lua/spawn.lua"):gsub("\\", "/")+ eq(1, vim.fn.filereadable(script))++ -- disposable cwd with a sentinel file that must survive+ local dir = vim.fn.tempname()+ vim.fn.mkdir(dir, "p")+ local sentinel = dir .. "/sentinel"+ vim.fn.writefile({ "keep" }, sentinel)++ -- simulate Neovim failing to create its tempdir (e.g. disk full), which+ -- makes `tempname()` return an empty string+ local spec = libuv.serialize({ contents = { "spawn-test" } }, true)+ local jobid = vim.fn.jobstart({+ vim.v.progpath,+ "--headless",+ "--clean",+ "--cmd",+ [[lua vim.fn.tempname = function() return "" end]],+ "-l",+ script,+ spec,+ }, { cwd = dir })+ eq(true, jobid > 0)+ local rc = vim.fn.jobwait({ jobid }, 10000)[1]+ eq(0, rc)++ eq(1, vim.fn.filereadable(sentinel))+ vim.fn.delete(dir, "rf")+ end)+end)