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"})
|
return vim.text.diff(a, b, {algorithm = "minimal"})
|
||||||
end
|
end
|
||||||
|
|
||||||
local create_save_file_path = function(buf_info)
|
local hash_path = function(path)
|
||||||
local encode = function(str)
|
return vim.fn.sha256(path)
|
||||||
return str:gsub("\r?\n", "\r\n"):gsub(
|
end
|
||||||
"([^%w%-%.%_%~ ])",
|
|
||||||
function(c)
|
local get_save_base_path = function(buf_info)
|
||||||
return string.format("%%%02X", string.byte(c))
|
return vim.fs.joinpath(haven_config.haven_path, hash_path(buf_info.name))
|
||||||
end
|
end
|
||||||
):gsub(" ", "+")
|
|
||||||
|
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
|
end
|
||||||
|
|
||||||
return vim.fs.joinpath(
|
return str:gsub("+", " "):gsub(
|
||||||
haven_config.haven_path,
|
"%%(%x%x)",
|
||||||
encode(buf_info.name) .. ".save"
|
function(x)
|
||||||
|
return string.char(tonumber(x, 16))
|
||||||
|
end
|
||||||
)
|
)
|
||||||
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)
|
local save_change_file = function(buf_info, lines, save_file)
|
||||||
active_saves[save_file] = nil
|
active_saves[save_file] = nil
|
||||||
|
|
||||||
|
if not save_source_file(buf_info) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local file, err = io.open(save_file, "a")
|
local file, err = io.open(save_file, "a")
|
||||||
if file == nil then
|
if file == nil then
|
||||||
print_message(true, err)
|
print_message(true, err)
|
||||||
@@ -203,7 +239,7 @@ local read_change_file = function(save_file)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local process_file_changed = function(buf_info)
|
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 changed_data = changed_lookup[save_file]
|
||||||
local immediate = vim.fn.filereadable(save_file) == 0
|
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
|
if buf_info ~= nil and #buf_info > 0 then
|
||||||
buf_info = buf_info[1]
|
buf_info = buf_info[1]
|
||||||
if buf_info.name:len() ~= 0 and vim.fn.filereadable(buf_info.name) ~= 0 then
|
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
|
for _, is_included in pairs(haven_config.inclusions) do
|
||||||
if is_included(buf_info.name, haven_config) then
|
if is_included(buf_info.name, haven_config) then
|
||||||
return true, buf_info
|
return true, buf_info
|
||||||
@@ -555,6 +591,95 @@ local show_picker = function(entries)
|
|||||||
):find()
|
):find()
|
||||||
end
|
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)
|
M.setup = function(config)
|
||||||
if config == nil then
|
if config == nil then
|
||||||
config = {}
|
config = {}
|
||||||
@@ -641,37 +766,46 @@ M.setup = function(config)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
migrate()
|
||||||
setup_autocmds()
|
setup_autocmds()
|
||||||
end
|
end
|
||||||
|
|
||||||
M.clean = function()
|
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 =
|
local history_files =
|
||||||
scan.scan_dir(haven_config.haven_path, {hidden = true, depth = 1})
|
scan.scan_dir(haven_config.haven_path, {hidden = true, depth = 1})
|
||||||
|
|
||||||
for _, history_file in ipairs(history_files) do
|
for _, history_file in ipairs(history_files) do
|
||||||
local source_path =
|
if history_file:ends_with(".src") then
|
||||||
Path:new(
|
local src_path = Path:new(history_file)
|
||||||
decode(Path:new(history_file):make_relative(haven_config.haven_path)):sub(
|
local file, err = io.open(history_file, "r")
|
||||||
1,
|
|
||||||
-6
|
if file == nil then
|
||||||
)
|
print_message(true, err)
|
||||||
)
|
else
|
||||||
if not source_path:exists() then
|
local original_path = file:read("*l") or ""
|
||||||
local history_path = Path:new(history_file)
|
file:close()
|
||||||
print("removing: " .. history_path:absolute())
|
|
||||||
history_path:rm()
|
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
|
end
|
||||||
end
|
end
|
||||||
@@ -697,7 +831,7 @@ M.history = function(bufname)
|
|||||||
local buf_info = vim.fn.getbufinfo(bufname)
|
local buf_info = vim.fn.getbufinfo(bufname)
|
||||||
if buf_info ~= nil and #buf_info > 0 then
|
if buf_info ~= nil and #buf_info > 0 then
|
||||||
buf_info = buf_info[1]
|
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
|
if vim.fn.filereadable(save_file) ~= 0 then
|
||||||
local entries, err = read_change_file(save_file)
|
local entries, err = read_change_file(save_file)
|
||||||
if entries == nil then
|
if entries == nil then
|
||||||
|
|||||||
Reference in New Issue
Block a user