fix(nb): additional sops.lua bug fixes
- Use nvim_buf_get_name(args.buf) instead of vim.fn.expand("%:p") in BufReadPost
- Add timeout to encrypt operation to prevent infinite hangs
- Add microsecond precision to temp file names to prevent collisions
- Strip trailing newline before vim.split to avoid extra empty lines
- Add trailing newline when writing temp file for POSIX compliance
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -53,7 +53,7 @@ vim.api.nvim_create_autocmd("BufReadPost", {
|
|||||||
group = sops_group,
|
group = sops_group,
|
||||||
pattern = secrets_patterns,
|
pattern = secrets_patterns,
|
||||||
callback = function(args)
|
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
|
-- Only decrypt if file exists and has content
|
||||||
if vim.fn.filereadable(filepath) == 1 and vim.fn.getfsize(filepath) > 0 then
|
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)
|
detach_lsp_clients(args.buf)
|
||||||
|
|
||||||
-- Replace buffer content with decrypted content
|
-- 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)
|
-- Mark buffer as not modified (since we just loaded it)
|
||||||
vim.bo[args.buf].modified = false
|
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)
|
-- This avoids /dev/stdin issues while keeping secrets secure (not in /tmp)
|
||||||
local dir = vim.fn.fnamemodify(filepath, ":h")
|
local dir = vim.fn.fnamemodify(filepath, ":h")
|
||||||
local filename = vim.fn.fnamemodify(filepath, ":t")
|
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
|
-- Write plaintext content to temp file
|
||||||
local temp_f, temp_err = io.open(temp_file, "w")
|
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)
|
vim.notify("SOPS: Failed to create temp file: " .. (temp_err or "unknown error"), vim.log.levels.ERROR)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
temp_f:write(content)
|
temp_f:write(content .. "\n")
|
||||||
temp_f:close()
|
temp_f:close()
|
||||||
|
|
||||||
-- Encrypt temp file with filename override so SOPS matches .sops.yaml rules
|
-- Encrypt temp file with filename override so SOPS matches .sops.yaml rules
|
||||||
-- Uses real filepath for rule matching, temp file for content
|
-- 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(filepath),
|
||||||
vim.fn.shellescape(temp_file))
|
vim.fn.shellescape(temp_file))
|
||||||
local encrypted = vim.fn.system(cmd)
|
local encrypted = vim.fn.system(cmd)
|
||||||
@@ -187,6 +189,15 @@ vim.api.nvim_create_autocmd("BufWriteCmd", {
|
|||||||
-- Always clean up temp file, even on error
|
-- Always clean up temp file, even on error
|
||||||
os.remove(temp_file)
|
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
|
if sops_exit_code == 0 then
|
||||||
-- Write encrypted content directly to file
|
-- Write encrypted content directly to file
|
||||||
local file, file_err = io.open(filepath, "w")
|
local file, file_err = io.open(filepath, "w")
|
||||||
@@ -212,7 +223,8 @@ vim.api.nvim_create_autocmd("BufWriteCmd", {
|
|||||||
detach_lsp_clients(args.buf)
|
detach_lsp_clients(args.buf)
|
||||||
|
|
||||||
-- Replace buffer with decrypted content
|
-- 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
|
-- Mark as not modified since we just saved
|
||||||
vim.bo[args.buf].modified = false
|
vim.bo[args.buf].modified = false
|
||||||
|
|||||||
Reference in New Issue
Block a user