fix nvim-haven failure on path too long

This commit is contained in:
2026-04-15 18:26:44 +00:00
parent 9b9716f372
commit 82503090f1
+172 -38
View File
@@ -117,25 +117,61 @@ local diff_strings = function(a, b)
return vim.text.diff(a, b, {algorithm = "minimal"})
end
local create_save_file_path = function(buf_info)
local encode = function(str)
return str:gsub("\r?\n", "\r\n"):gsub(
"([^%w%-%.%_%~ ])",
function(c)
return string.format("%%%02X", string.byte(c))
end
):gsub(" ", "+")
local hash_path = function(path)
return vim.fn.sha256(path)
end
local get_save_base_path = function(buf_info)
return vim.fs.joinpath(haven_config.haven_path, hash_path(buf_info.name))
end
local create_save_data_file_path = function(buf_info)
return get_save_base_path(buf_info) .. ".data"
end
local create_save_src_file_path = function(buf_info)
return get_save_base_path(buf_info) .. ".src"
end
local legacy_decode = function(str)
if str == nil then
return ""
end
return vim.fs.joinpath(
haven_config.haven_path,
encode(buf_info.name) .. ".save"
return str:gsub("+", " "):gsub(
"%%(%x%x)",
function(x)
return string.char(tonumber(x, 16))
end
)
end
local save_source_file = function(buf_info)
local src_file = create_save_src_file_path(buf_info)
local file, err = io.open(src_file, "w+")
if file == nil then
print_message(true, err)
return false
end
_, err = file:write(buf_info.name .. line_ending)
if err ~= nil then
print_message(true, err)
file:close()
return false
end
file:close()
return true
end
local save_change_file = function(buf_info, lines, save_file)
active_saves[save_file] = nil
if not save_source_file(buf_info) then
return
end
local file, err = io.open(save_file, "a")
if file == nil then
print_message(true, err)
@@ -203,7 +239,7 @@ local read_change_file = function(save_file)
end
local process_file_changed = function(buf_info)
local save_file = create_save_file_path(buf_info)
local save_file = create_save_data_file_path(buf_info)
local changed_data = changed_lookup[save_file]
local immediate = vim.fn.filereadable(save_file) == 0
@@ -270,7 +306,7 @@ local check_requirements = function()
if buf_info ~= nil and #buf_info > 0 then
buf_info = buf_info[1]
if buf_info.name:len() ~= 0 and vim.fn.filereadable(buf_info.name) ~= 0 then
if changed_lookup[create_save_file_path(buf_info)] == nil then
if changed_lookup[create_save_data_file_path(buf_info)] == nil then
for _, is_included in pairs(haven_config.inclusions) do
if is_included(buf_info.name, haven_config) then
return true, buf_info
@@ -555,6 +591,95 @@ local show_picker = function(entries)
):find()
end
local migrate = function()
local history_files =
scan.scan_dir(haven_config.haven_path, {hidden = true, depth = 1})
for _, history_file in ipairs(history_files) do
if history_file:ends_with(".save") then
local old_path_part =
Path:new(history_file):make_relative(haven_config.haven_path):sub(1, -6)
local original_path = legacy_decode(old_path_part)
if original_path == "" then
print_message(true, "skipping invalid legacy file: " .. history_file)
else
local new_data_file = create_save_data_file_path({name = original_path})
local new_src_file = create_save_src_file_path({name = original_path})
local old_file = io.open(history_file, "r")
if old_file == nil then
print_message(true, "failed to read legacy file: " .. history_file)
else
local contents = old_file:read("*a") or ""
old_file:close()
local data_ok = false
local src_ok = false
do
local f, err = io.open(new_data_file, "w+")
if f == nil then
print_message(true, err)
else
local ok, write_err = f:write(contents)
f:close()
if ok == nil then
print_message(true, write_err)
else
data_ok = true
end
end
end
do
local f, err = io.open(new_src_file, "w+")
if f == nil then
print_message(true, err)
else
local ok, write_err = f:write(original_path .. line_ending)
f:close()
if ok == nil then
print_message(true, write_err)
else
src_ok = true
end
end
end
if data_ok and src_ok then
local ok, rm_err = os.remove(history_file)
if ok then
print("migrated: " .. history_file)
else
print_message(
true,
"migration failed: " .. history_file .. " " .. tostring(rm_err)
)
end
else
print_message(true, "migration failed for: " .. history_file)
pcall(
function()
if Path:new(new_data_file):exists() then
Path:new(new_data_file):rm()
end
end
)
pcall(
function()
if Path:new(new_src_file):exists() then
Path:new(new_src_file):rm()
end
end
)
end
end
end
end
end
end
M.setup = function(config)
if config == nil then
config = {}
@@ -641,37 +766,46 @@ M.setup = function(config)
return
end
migrate()
setup_autocmds()
end
M.clean = function()
local decode = function(str)
if str == nil then
return ""
end
return str:gsub("+", " "):gsub(
"%%(%x%x)",
function(x)
return string.char(tonumber(x, 16))
end
)
end
local history_files =
scan.scan_dir(haven_config.haven_path, {hidden = true, depth = 1})
for _, history_file in ipairs(history_files) do
local source_path =
Path:new(
decode(Path:new(history_file):make_relative(haven_config.haven_path)):sub(
1,
-6
)
)
if not source_path:exists() then
local history_path = Path:new(history_file)
print("removing: " .. history_path:absolute())
history_path:rm()
if history_file:ends_with(".src") then
local src_path = Path:new(history_file)
local file, err = io.open(history_file, "r")
if file == nil then
print_message(true, err)
else
local original_path = file:read("*l") or ""
file:close()
if original_path == "" or not Path:new(original_path):exists() then
local base = history_file:sub(1, -5)
local data_file = base .. ".data"
if Path:new(data_file):exists() then
print("removing: " .. data_file)
pcall(
function()
Path:new(data_file):rm()
end
)
end
print("removing: " .. history_file)
pcall(
function()
src_path:rm()
end
)
end
end
end
end
end
@@ -697,7 +831,7 @@ M.history = function(bufname)
local buf_info = vim.fn.getbufinfo(bufname)
if buf_info ~= nil and #buf_info > 0 then
buf_info = buf_info[1]
local save_file = create_save_file_path(buf_info)
local save_file = create_save_data_file_path(buf_info)
if vim.fn.filereadable(save_file) ~= 0 then
local entries, err = read_change_file(save_file)
if entries == nil then