diff --git a/hosts/nb/modules/development/nvim/config/sops.lua b/hosts/nb/modules/development/nvim/config/sops.lua index 4a17e8a..d11a388 100644 --- a/hosts/nb/modules/development/nvim/config/sops.lua +++ b/hosts/nb/modules/development/nvim/config/sops.lua @@ -53,7 +53,7 @@ vim.api.nvim_create_autocmd("BufReadPost", { group = sops_group, pattern = secrets_patterns, callback = function(args) - local filepath = vim.fn.expand("%:p") + local filepath = vim.api.nvim_buf_get_name(args.buf) -- Only decrypt if file exists and has content if vim.fn.filereadable(filepath) == 1 and vim.fn.getfsize(filepath) > 0 then @@ -102,7 +102,8 @@ vim.api.nvim_create_autocmd("BufReadPost", { detach_lsp_clients(args.buf) -- Replace buffer content with decrypted content - vim.api.nvim_buf_set_lines(args.buf, 0, -1, false, vim.split(result, "\n")) + -- Strip trailing newline to avoid adding extra empty line + vim.api.nvim_buf_set_lines(args.buf, 0, -1, false, vim.split(result:gsub("\n$", ""), "\n")) -- Mark buffer as not modified (since we just loaded it) vim.bo[args.buf].modified = false @@ -165,7 +166,7 @@ vim.api.nvim_create_autocmd("BufWriteCmd", { -- This avoids /dev/stdin issues while keeping secrets secure (not in /tmp) local dir = vim.fn.fnamemodify(filepath, ":h") local filename = vim.fn.fnamemodify(filepath, ":t") - local temp_file = string.format("%s/.%s.sops_tmp_%d", dir, filename, os.time()) + local temp_file = string.format("%s/.%s.sops_tmp_%d_%d", dir, filename, os.time(), vim.loop.hrtime() % 1000000) -- Write plaintext content to temp file local temp_f, temp_err = io.open(temp_file, "w") @@ -173,12 +174,13 @@ vim.api.nvim_create_autocmd("BufWriteCmd", { vim.notify("SOPS: Failed to create temp file: " .. (temp_err or "unknown error"), vim.log.levels.ERROR) return end - temp_f:write(content) + temp_f:write(content .. "\n") temp_f:close() -- Encrypt temp file with filename override so SOPS matches .sops.yaml rules -- Uses real filepath for rule matching, temp file for content - local cmd = string.format("sops --encrypt --filename-override %s %s", + local cmd = string.format("timeout %d sops --encrypt --filename-override %s %s", + SOPS_TIMEOUT, vim.fn.shellescape(filepath), vim.fn.shellescape(temp_file)) local encrypted = vim.fn.system(cmd) @@ -187,6 +189,15 @@ vim.api.nvim_create_autocmd("BufWriteCmd", { -- Always clean up temp file, even on error os.remove(temp_file) + -- Check for timeout (exit code 124 from timeout command) + if sops_exit_code == 124 then + vim.notify( + string.format("SOPS: Encryption timed out after %d seconds.", SOPS_TIMEOUT), + vim.log.levels.ERROR + ) + return + end + if sops_exit_code == 0 then -- Write encrypted content directly to file local file, file_err = io.open(filepath, "w") @@ -212,7 +223,8 @@ vim.api.nvim_create_autocmd("BufWriteCmd", { detach_lsp_clients(args.buf) -- Replace buffer with decrypted content - vim.api.nvim_buf_set_lines(args.buf, 0, -1, false, vim.split(decrypted, "\n")) + -- Strip trailing newline to avoid adding extra empty line + vim.api.nvim_buf_set_lines(args.buf, 0, -1, false, vim.split(decrypted:gsub("\n$", ""), "\n")) -- Mark as not modified since we just saved vim.bo[args.buf].modified = false