From dbc0fa9bd6831ea060df410b70de32627c5c1f68 Mon Sep 17 00:00:00 2001 From: Raphael Date: Wed, 3 Apr 2024 18:44:57 +0800 Subject: [PATCH] fix(stdpath): remove duplicate directories (#26653) --- src/nvim/os/stdpaths.c | 47 +++++++++++++++++++++++ test/functional/options/defaults_spec.lua | 16 ++++---- 2 files changed, 55 insertions(+), 8 deletions(-) diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c index ede17bc7c8..187a0e0674 100644 --- a/src/nvim/os/stdpaths.c +++ b/src/nvim/os/stdpaths.c @@ -2,13 +2,16 @@ #include #include +#include "klib/kvec.h" #include "nvim/ascii_defs.h" #include "nvim/fileio.h" #include "nvim/globals.h" #include "nvim/memory.h" #include "nvim/os/os.h" +#include "nvim/os/os_defs.h" #include "nvim/os/stdpaths_defs.h" #include "nvim/path.h" +#include "nvim/strings.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/stdpaths.c.generated.h" @@ -93,6 +96,46 @@ bool appname_is_valid(void) return true; } +/// Remove duplicate directories in the given XDG directory. +/// @param[in] List of directories possibly with duplicates +/// @param[out] List of directories without duplicates +static char *xdg_remove_duplicate(char *ret, const char *sep) +{ + kvec_t(char *) data = KV_INITIAL_VALUE; + char *saveptr; + + char *token = os_strtok(ret, sep, &saveptr); + while (token != NULL) { + // Check if the directory is not already in the list + bool is_duplicate = false; + for (size_t i = 0; i < data.size; i++) { + if (path_fnamecmp(kv_A(data, i), token) == 0) { + is_duplicate = true; + break; + } + } + // If it's not a duplicate, add it to the list + if (!is_duplicate) { + kv_push(data, token); + } + token = os_strtok(NULL, sep, &saveptr); + } + + StringBuilder result = KV_INITIAL_VALUE; + + for (size_t i = 0; i < data.size; i++) { + if (i == 0) { + kv_printf(result, "%s", kv_A(data, i)); + } else { + kv_printf(result, "%s%s", sep, kv_A(data, i)); + } + } + + kv_destroy(data); + xfree(ret); + return result.items; +} + /// Return XDG variable value /// /// @param[in] idx XDG variable to use. @@ -131,6 +174,10 @@ char *stdpaths_get_xdg_var(const XDGVarType idx) ret = xmemdupz(ret, len >= 2 ? len - 1 : 0); // Trim trailing slash. } + if ((idx == kXDGDataDirs || idx == kXDGConfigDirs) && ret != NULL) { + ret = xdg_remove_duplicate(ret, ENV_SEPSTR); + } + return ret; } diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua index 2d3d827619..5e98453565 100644 --- a/test/functional/options/defaults_spec.lua +++ b/test/functional/options/defaults_spec.lua @@ -378,7 +378,7 @@ describe('XDG defaults', function() .. root_path .. ('/b'):rep(2048) .. '/nvim' - .. (',' .. root_path .. '/c/nvim'):rep(512) + .. (',' .. root_path .. '/c/nvim') .. ',' .. root_path .. ('/X'):rep(4096) @@ -393,12 +393,12 @@ describe('XDG defaults', function() .. root_path .. ('/B'):rep(2048) .. '/nvim/site' - .. (',' .. root_path .. '/C/nvim/site'):rep(512) + .. (',' .. root_path .. '/C/nvim/site') .. ',' .. vimruntime .. ',' .. libdir - .. (',' .. root_path .. '/C/nvim/site/after'):rep(512) + .. (',' .. root_path .. '/C/nvim/site/after') .. ',' .. root_path .. ('/B'):rep(2048) @@ -413,7 +413,7 @@ describe('XDG defaults', function() .. '/' .. data_dir .. '/site/after' - .. (',' .. root_path .. '/c/nvim/after'):rep(512) + .. (',' .. root_path .. '/c/nvim/after') .. ',' .. root_path .. ('/b'):rep(2048) @@ -449,7 +449,7 @@ describe('XDG defaults', function() .. root_path .. ('/b'):rep(2048) .. '/nvim' - .. (',' .. root_path .. '/c/nvim'):rep(512) + .. (',' .. root_path .. '/c/nvim') .. ',' .. root_path .. ('/X'):rep(4096) @@ -464,12 +464,12 @@ describe('XDG defaults', function() .. root_path .. ('/B'):rep(2048) .. '/nvim/site' - .. (',' .. root_path .. '/C/nvim/site'):rep(512) + .. (',' .. root_path .. '/C/nvim/site') .. ',' .. vimruntime .. ',' .. libdir - .. (',' .. root_path .. '/C/nvim/site/after'):rep(512) + .. (',' .. root_path .. '/C/nvim/site/after') .. ',' .. root_path .. ('/B'):rep(2048) @@ -484,7 +484,7 @@ describe('XDG defaults', function() .. '/' .. data_dir .. '/site/after' - .. (',' .. root_path .. '/c/nvim/after'):rep(512) + .. (',' .. root_path .. '/c/nvim/after') .. ',' .. root_path .. ('/b'):rep(2048)