aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-07-12 07:10:31 +0800
committerGitHub <noreply@github.com>2024-07-12 07:10:31 +0800
commita5de650f0eb93a848831f1ba631485437a82d57b (patch)
treeb56e10b64b915ce45c665a682667daba447ab1b7
parent31d53cbb0fff48488f45ba234b8d595c31507739 (diff)
parent80818641f3504eb57a4fae5003f234f5f5f19ba1 (diff)
downloadrneovim-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.c52
-rw-r--r--src/nvim/tag.c4
-rw-r--r--test/old/testdir/test_findfile.vim92
-rw-r--r--test/old/testdir/test_taglist.vim32
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([