vim-patch:9.1.0569: fnamemodify() treats ".." and "../" differently (#29673)

Problem:  fnamemodify() treats ".." and "../" differently.
Solution: Expand ".." properly like how "/.." is treated in 8.2.3388.
          (zeertzjq)

closes: vim/vim#15218

1ee7420460
(cherry picked from commit 028dd3c5c4)
This commit is contained in:
zeertzjq 2024-07-12 14:30:49 +08:00 committed by github-actions[bot]
parent bddbbd874c
commit ceb82a9396
5 changed files with 47 additions and 22 deletions

View File

@ -2384,9 +2384,13 @@ static int path_to_absolute(const char *fname, char *buf, size_t len, int force)
p = strrchr(fname, '\\');
}
#endif
if (p == NULL && strcmp(fname, "..") == 0) {
// Handle ".." without path separators.
p = fname + 2;
}
if (p != NULL) {
if (strcmp(p + 1, "..") == 0) {
// for "/path/dir/.." include the "/.."
if (vim_ispathsep_nocolon(*p) && strcmp(p + 1, "..") == 0) {
// For "/path/dir/.." include the "/..".
p += 3;
}
assert(p >= fname);

View File

@ -107,6 +107,9 @@ func Test_findfile()
let l = findfile('bar', ';../', -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))
@ -117,6 +120,9 @@ func Test_findfile()
let l = findfile('bar', ';../../', -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/', -1)
call assert_equal(2, len(l))
@ -130,6 +136,10 @@ func Test_findfile()
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('.*/Xfinddir1/Xdir2/Xdir3/bar', l[0])
call assert_match('.*/Xfinddir1/bar', l[1])
" Test combined downwards and upwards search from Xdir2/.
cd ../..

View File

@ -14,6 +14,8 @@ func Test_fnamemodify()
call assert_equal($HOME .. "/foo" , fnamemodify('~/foo', ':p'))
call assert_equal(fnamemodify('.', ':p:h:h:h') .. '/', fnamemodify($HOME .. '/../', ':p'))
call assert_equal(fnamemodify('.', ':p:h:h:h') .. '/', fnamemodify($HOME .. '/..', ':p'))
call assert_equal(fnamemodify('.', ':p:h:h') .. '/', fnamemodify('../', ':p'))
call assert_equal(fnamemodify('.', ':p:h:h') .. '/', fnamemodify('..', ':p'))
call assert_equal('test.out', fnamemodify('test.out', ':.'))
call assert_equal('a', fnamemodify('../testdir/a', ':.'))
call assert_equal('~/testdir/test.out', fnamemodify('test.out', ':~'))

View File

@ -143,15 +143,15 @@ func Test_tagfiles_stopdir()
call writefile([], 'Xtagsdir1/Xtags', 'D')
cd Xtagsdir1/
let &tags = './Xtags;' .. fnamemodify('./..', ':p')
let &tags = './Xtags;' .. fnamemodify('..', ':p')
call assert_equal(1, len(tagfiles()))
cd Xtagsdir2/
let &tags = './Xtags;' .. fnamemodify('./..', ':p')
let &tags = './Xtags;' .. fnamemodify('..', ':p')
call assert_equal(1, len(tagfiles()))
cd Xtagsdir3/
let &tags = './Xtags;' .. fnamemodify('./..', ':p')
let &tags = './Xtags;' .. fnamemodify('..', ':p')
call assert_equal(0, len(tagfiles()))
let &tags = './Xtags;../'
@ -163,6 +163,15 @@ func Test_tagfiles_stopdir()
cd ..
call assert_equal(1, len(tagfiles()))
let &tags = './Xtags;..'
call assert_equal(1, len(tagfiles()))
cd Xtagsdir2/
call assert_equal(1, len(tagfiles()))
cd Xtagsdir3/
call assert_equal(0, len(tagfiles()))
set tags&
call chdir(save_cwd)
endfunc

View File

@ -468,8 +468,11 @@ describe('path.c', function()
eq(OK, result)
end)
itp('concatenates directory name if it does not contain a slash', function()
local expected = uv.cwd() .. '/..'
itp('produces absolute path for .. without a slash', function()
local old_dir = uv.cwd()
uv.chdir('..')
local expected = uv.cwd()
uv.chdir(old_dir)
local filename = '..'
local buflen = get_buf_len(expected, filename)
local do_expand = 1
@ -478,9 +481,7 @@ describe('path.c', function()
eq(OK, result)
end)
itp(
'enters given directory (instead of just concatenating the strings) if possible and if path contains a slash',
function()
itp('produces absolute path if possible and if path contains a slash', function()
local old_dir = uv.cwd()
uv.chdir('..')
local expected = uv.cwd() .. '/test.file'
@ -491,8 +492,7 @@ describe('path.c', function()
local buf, result = vim_FullName(filename, buflen, do_expand)
eq(expected, ffi.string(buf))
eq(OK, result)
end
)
end)
itp('just copies the path if it is already absolute and force=0', function()
local absolute_path = '/absolute/path'