fix nvim-haven failure on path too long
This commit is contained in:
+172
-38
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user