Skip to content

Dictionary write corruption if same filename #14

@YodaEmbedding

Description

@YodaEmbedding

Consider:

function M.update_dictionary_files(dictionaries)
	for lang, dict in pairs(dictionaries) do
		M.write(filename, table.concat(dict, "\n") .. "\n")
	end
end

This leads to file corruption if filenames are identical for different langs. For instance, lang = en-US and lang = en-GB will both write to a file named en.utf-8.add.

To fix this:

diff --git a/lua/ltex-utils/settings_io.lua b/lua/ltex-utils/settings_io.lua
index cdbe4b6..ed8c45e 100644
--- a/lua/ltex-utils/settings_io.lua
+++ b/lua/ltex-utils/settings_io.lua
@@ -169,17 +169,21 @@ end
 function M.update_dictionary_files(dictionaries)
 	---@type string[]
 	local used_langs = {}
+	local used_filenames = {}
 	for lang, dict in pairs(dictionaries) do
 		---@type string
 		local filename = Config.dictionary.path ..
 											Config.dictionary.filename(lang)
-		---@type string[]|nil
-		local saved_dict = M.read_dictionary(filename)
-		-- if there is already a saved dictionary merge it with current one
-		if saved_dict then
-			dict = table_utils.merge_lists_unique(dict, saved_dict)
+		if not vim.tbl_contains(used_filenames, filename) then
+			---@type string[]|nil
+			local saved_dict = M.read_dictionary(filename)
+			-- if there is already a saved dictionary merge it with current one
+			if saved_dict then
+				dict = table_utils.merge_lists_unique(dict, saved_dict)
+			end
+			M.write(filename, table.concat(dict, "\n") .. "\n")
 		end
-		M.write(filename, table.concat(dict, "\n") .. "\n")
+		table.insert(used_filenames, filename)
 		table.insert(used_langs, lang)
 	end

Also, while we're at it, let's also write the output in a deterministic order for people (like me) who save their dictionaries in version control:

diff --git a/lua/ltex-utils/table_utils.lua b/lua/ltex-utils/table_utils.lua
index 168ab5d..d5f4455 100644
--- a/lua/ltex-utils/table_utils.lua
+++ b/lua/ltex-utils/table_utils.lua
@@ -49,6 +49,8 @@ function M.merge_lists_unique(list1, list2, changes)
 	---@type string[]
 	local merged_list = vim.tbl_keys(unique_elements)
 
+  table.sort(merged_list)
+
 	return merged_list
 end

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions