diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-07-12 07:10:31 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-12 07:10:31 +0800 |
commit | a5de650f0eb93a848831f1ba631485437a82d57b (patch) | |
tree | b56e10b64b915ce45c665a682667daba447ab1b7 | |
parent | 31d53cbb0fff48488f45ba234b8d595c31507739 (diff) | |
parent | 80818641f3504eb57a4fae5003f234f5f5f19ba1 (diff) | |
download | rneovim-a5de650f0eb93a848831f1ba631485437a82d57b.tar.gz rneovim-a5de650f0eb93a848831f1ba631485437a82d57b.tar.bz2 rneovim-a5de650f0eb93a848831f1ba631485437a82d57b.zip |
Merge pull request #29668 from zeertzjq/vim-9.1.0562
vim-patch:9.1.{0562,0565,0566,0567}: file search fixes
-rw-r--r-- | src/nvim/file_search.c | 52 | ||||
-rw-r--r-- | src/nvim/tag.c | 4 | ||||
-rw-r--r-- | test/old/testdir/test_findfile.vim | 92 | ||||
-rw-r--r-- | test/old/testdir/test_taglist.vim | 32 |
4 files changed, 119 insertions, 61 deletions
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index b6a039af5e..5760fc864a 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -349,23 +349,24 @@ void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, i search_ctx->ffsc_stopdirs_v = xmalloc(sizeof(char *)); do { - char *helper; - void *ptr; - - helper = walker; - ptr = xrealloc(search_ctx->ffsc_stopdirs_v, - (dircount + 1) * sizeof(char *)); + char *helper = walker; + void *ptr = xrealloc(search_ctx->ffsc_stopdirs_v, + (dircount + 1) * sizeof(char *)); search_ctx->ffsc_stopdirs_v = ptr; walker = vim_strchr(walker, ';'); + assert(!walker || walker - helper >= 0); + size_t len = walker ? (size_t)(walker - helper) : strlen(helper); + // "" means ascent till top of directory tree. + if (*helper != NUL && !vim_isAbsName(helper) && len + 1 < MAXPATHL) { + // Make the stop dir an absolute path name. + xmemcpyz(ff_expand_buffer, helper, len); + search_ctx->ffsc_stopdirs_v[dircount - 1] = FullName_save(helper, len); + } else { + search_ctx->ffsc_stopdirs_v[dircount - 1] = xmemdupz(helper, len); + } if (walker) { - assert(walker - helper >= 0); - search_ctx->ffsc_stopdirs_v[dircount - 1] = xstrnsave(helper, (size_t)(walker - helper)); walker++; - } else { - // this might be "", which means ascent till top of directory tree. - search_ctx->ffsc_stopdirs_v[dircount - 1] = xstrdup(helper); } - dircount++; } while (walker != NULL); search_ctx->ffsc_stopdirs_v[dircount - 1] = NULL; @@ -892,11 +893,12 @@ char *vim_findfile(void *search_ctx_arg) if (search_ctx->ffsc_start_dir && search_ctx->ffsc_stopdirs_v != NULL && !got_int) { ff_stack_T *sptr; + // path_end may point to the NUL or the previous path separator + ptrdiff_t plen = (path_end - search_ctx->ffsc_start_dir) + (*path_end != NUL); // is the last starting directory in the stop list? if (ff_path_in_stoplist(search_ctx->ffsc_start_dir, - (int)(path_end - search_ctx->ffsc_start_dir), - search_ctx->ffsc_stopdirs_v)) { + (size_t)plen, search_ctx->ffsc_stopdirs_v)) { break; } @@ -1231,7 +1233,7 @@ static void ff_clear(ff_search_ctx_T *search_ctx) /// check if the given path is in the stopdirs /// /// @return true if yes else false -static bool ff_path_in_stoplist(char *path, int path_len, char **stopdirs_v) +static bool ff_path_in_stoplist(char *path, size_t path_len, char **stopdirs_v) { // eat up trailing path separators, except the first while (path_len > 1 && vim_ispathsep(path[path_len - 1])) { @@ -1244,20 +1246,16 @@ static bool ff_path_in_stoplist(char *path, int path_len, char **stopdirs_v) } for (int i = 0; stopdirs_v[i] != NULL; i++) { - if ((int)strlen(stopdirs_v[i]) > path_len) { - // match for parent directory. So '/home' also matches - // '/home/rks'. Check for PATHSEP in stopdirs_v[i], else - // '/home/r' would also match '/home/rks' - if (path_fnamencmp(stopdirs_v[i], path, (size_t)path_len) == 0 - && vim_ispathsep(stopdirs_v[i][path_len])) { - return true; - } - } else { - if (path_fnamecmp(stopdirs_v[i], path) == 0) { - return true; - } + // match for parent directory. So '/home' also matches + // '/home/rks'. Check for PATHSEP in stopdirs_v[i], else + // '/home/r' would also match '/home/rks' + if (path_fnamencmp(stopdirs_v[i], path, path_len) == 0 + && (strlen(stopdirs_v[i]) <= path_len + || vim_ispathsep(stopdirs_v[i][path_len]))) { + return true; } } + return false; } diff --git a/src/nvim/tag.c b/src/nvim/tag.c index 90269c776e..cc7ff070c2 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -2583,6 +2583,10 @@ int get_tagfname(tagname_T *tnp, int first, char *buf) // move the filename one char forward and truncate the // filepath with a NUL filename = path_tail(buf); + if (r_ptr != NULL) { + STRMOVE(r_ptr + 1, r_ptr); + r_ptr++; + } STRMOVE(filename + 1, filename); *filename++ = NUL; diff --git a/test/old/testdir/test_findfile.vim b/test/old/testdir/test_findfile.vim index 0f4b30aec2..0b241e3466 100644 --- a/test/old/testdir/test_findfile.vim +++ b/test/old/testdir/test_findfile.vim @@ -1,14 +1,14 @@ " Test findfile() and finddir() -let s:files = [ 'Xdir1/foo', - \ 'Xdir1/bar', - \ 'Xdir1/Xdir2/foo', - \ 'Xdir1/Xdir2/foobar', - \ 'Xdir1/Xdir2/Xdir3/bar', - \ 'Xdir1/Xdir2/Xdir3/barfoo' ] +let s:files = [ 'Xfinddir1/foo', + \ 'Xfinddir1/bar', + \ 'Xfinddir1/Xdir2/foo', + \ 'Xfinddir1/Xdir2/foobar', + \ 'Xfinddir1/Xdir2/Xdir3/bar', + \ 'Xfinddir1/Xdir2/Xdir3/barfoo' ] func CreateFiles() - call mkdir('Xdir1/Xdir2/Xdir3/Xdir2', 'p') + call mkdir('Xfinddir1/Xdir2/Xdir3/Xdir2', 'p') for f in s:files call writefile([], f) endfor @@ -16,15 +16,15 @@ endfunc func CleanFiles() " Safer to delete each file even if it's more verbose - " than doing a recursive delete('Xdir1', 'rf'). + " than doing a recursive delete('Xfinddir1', 'rf'). for f in s:files call delete(f) endfor - call delete('Xdir1/Xdir2/Xdir3/Xdir2', 'd') - call delete('Xdir1/Xdir2/Xdir3', 'd') - call delete('Xdir1/Xdir2', 'd') - call delete('Xdir1', 'd') + call delete('Xfinddir1/Xdir2/Xdir3/Xdir2', 'd') + call delete('Xfinddir1/Xdir2/Xdir3', 'd') + call delete('Xfinddir1/Xdir2', 'd') + call delete('Xfinddir1', 'd') endfunc " Test findfile({name} [, {path} [, {count}]]) @@ -34,7 +34,7 @@ func Test_findfile() let save_dir = getcwd() set shellslash call CreateFiles() - cd Xdir1 + cd Xfinddir1 e Xdir2/foo " With ,, in path, findfile() searches in current directory. @@ -83,34 +83,58 @@ func Test_findfile() " Test upwards search. cd Xdir2/Xdir3 call assert_equal('bar', findfile('bar', ';')) - call assert_match('.*/Xdir1/Xdir2/foo', findfile('foo', ';')) - call assert_match('.*/Xdir1/Xdir2/foo', findfile('foo', ';', 1)) - call assert_match('.*/Xdir1/foo', findfile('foo', ';', 2)) - call assert_match('.*/Xdir1/foo', findfile('foo', ';', 2)) - call assert_match('.*/Xdir1/Xdir2/foo', findfile('foo', 'Xdir2;', 1)) + call assert_match('.*/Xfinddir1/Xdir2/foo', findfile('foo', ';')) + call assert_match('.*/Xfinddir1/Xdir2/foo', findfile('foo', ';', 1)) + call assert_match('.*/Xfinddir1/foo', findfile('foo', ';', 2)) + call assert_match('.*/Xfinddir1/foo', findfile('foo', ';', 2)) + call assert_match('.*/Xfinddir1/Xdir2/foo', findfile('foo', 'Xdir2;', 1)) call assert_equal('', findfile('foo', 'Xdir2;', 2)) " List l should have at least 2 values (possibly more if foo file - " happens to be found upwards above Xdir1). + " happens to be found upwards above Xfinddir1). let l = findfile('foo', ';', -1) - call assert_match('.*/Xdir1/Xdir2/foo', l[0]) - call assert_match('.*/Xdir1/foo', l[1]) + call assert_match('.*/Xfinddir1/Xdir2/foo', l[0]) + call assert_match('.*/Xfinddir1/foo', l[1]) " Test upwards search with stop-directory. cd Xdir2 - let l = findfile('bar', ';' . save_dir . '/Xdir1/Xdir2/', -1) + let l = findfile('bar', ';' . save_dir . '/Xfinddir1/Xdir2/Xdir3/', -1) call assert_equal(1, len(l)) - call assert_match('.*/Xdir1/Xdir2/Xdir3/bar', l[0]) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + let l = findfile('bar', ';' . save_dir . '/Xfinddir1/Xdir2/Xdir3', -1) + call assert_equal(1, len(l)) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + let l = findfile('bar', ';../', -1) + call assert_equal(1, len(l)) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + + let l = findfile('bar', ';' . save_dir . '/Xfinddir1/Xdir2/', -1) + call assert_equal(1, len(l)) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + let l = findfile('bar', ';' . save_dir . '/Xfinddir1/Xdir2', -1) + call assert_equal(1, len(l)) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + let l = findfile('bar', ';../../', -1) + call assert_equal(1, len(l)) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) - let l = findfile('bar', ';' . save_dir . '/Xdir1/', -1) + let l = findfile('bar', ';' . save_dir . '/Xfinddir1/', -1) + call assert_equal(2, len(l)) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + call assert_match('.*/Xfinddir1/bar', l[1]) + let l = findfile('bar', ';' . save_dir . '/Xfinddir1', -1) + call assert_equal(2, len(l)) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + call assert_match('.*/Xfinddir1/bar', l[1]) + let l = findfile('bar', ';../../../', -1) call assert_equal(2, len(l)) - call assert_match('.*/Xdir1/Xdir2/Xdir3/bar', l[0]) - call assert_match('.*/Xdir1/bar', l[1]) + call assert_match('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0]) + call assert_match('.*/Xfinddir1/bar', l[1]) " Test combined downwards and upwards search from Xdir2/. cd ../.. call assert_equal('Xdir3/bar', findfile('bar', '**;', 1)) - call assert_match('.*/Xdir1/bar', findfile('bar', '**;', 2)) + call assert_match('.*/Xfinddir1/bar', findfile('bar', '**;', 2)) bwipe! call chdir(save_dir) @@ -135,7 +159,7 @@ func Test_finddir() set path=,, set shellslash call CreateFiles() - cd Xdir1 + cd Xfinddir1 call assert_equal('Xdir2', finddir('Xdir2')) call assert_equal('', 'Xdir3'->finddir()) @@ -158,17 +182,17 @@ func Test_finddir() " Test upwards dir search. cd Xdir2/Xdir3 - call assert_match('.*/Xdir1', finddir('Xdir1', ';')) + call assert_match('.*/Xfinddir1', finddir('Xfinddir1', ';')) " Test upwards search with stop-directory. - call assert_match('.*/Xdir1', finddir('Xdir1', ';' . save_dir . '/')) - call assert_equal('', finddir('Xdir1', ';' . save_dir . '/Xdir1/')) + call assert_match('.*/Xfinddir1', finddir('Xfinddir1', ';' . save_dir . '/')) + call assert_equal('', finddir('Xfinddir1', ';' . save_dir . '/Xfinddir1/')) " Test combined downwards and upwards dir search from Xdir2/. cd .. - call assert_match('.*/Xdir1', finddir('Xdir1', '**;', 1)) + call assert_match('.*/Xfinddir1', finddir('Xfinddir1', '**;', 1)) call assert_equal('Xdir3/Xdir2', finddir('Xdir2', '**;', 1)) - call assert_match('.*/Xdir1/Xdir2', finddir('Xdir2', '**;', 2)) + call assert_match('.*/Xfinddir1/Xdir2', finddir('Xdir2', '**;', 2)) call assert_equal('Xdir3', finddir('Xdir3', '**;', 1)) call chdir(save_dir) @@ -192,7 +216,7 @@ func Test_find_cmd() let save_dir = getcwd() set path=.,./**/* call CreateFiles() - cd Xdir1 + cd Xfinddir1 " Test for :find find foo diff --git a/test/old/testdir/test_taglist.vim b/test/old/testdir/test_taglist.vim index 75d28c3ec4..92d6d283ed 100644 --- a/test/old/testdir/test_taglist.vim +++ b/test/old/testdir/test_taglist.vim @@ -135,6 +135,38 @@ func Test_tagsfile_without_trailing_newline() set tags& endfunc +" Check that specifying a stop directory in 'tags' works properly. +func Test_tagfiles_stopdir() + let save_cwd = getcwd() + + call mkdir('Xtagsdir1/Xtagsdir2/Xtagsdir3', 'pR') + call writefile([], 'Xtagsdir1/Xtags', 'D') + + cd Xtagsdir1/ + let &tags = './Xtags;' .. fnamemodify('./..', ':p') + call assert_equal(1, len(tagfiles())) + + cd Xtagsdir2/ + let &tags = './Xtags;' .. fnamemodify('./..', ':p') + call assert_equal(1, len(tagfiles())) + + cd Xtagsdir3/ + let &tags = './Xtags;' .. fnamemodify('./..', ':p') + call assert_equal(0, len(tagfiles())) + + let &tags = './Xtags;../' + call assert_equal(0, len(tagfiles())) + + cd .. + call assert_equal(1, len(tagfiles())) + + cd .. + call assert_equal(1, len(tagfiles())) + + set tags& + call chdir(save_cwd) +endfunc + " Test for ignoring comments in a tags file func Test_tagfile_ignore_comments() call writefile([ |