mirror of
https://github.com/neovim/neovim.git
synced 2026-04-22 15:25:30 +00:00
fix(fs): expand drive-relative paths on Windows #37084
Problem: On windows, if a drive-relative path doesn't contain a slash, `path_to_absolute` can't split out the relative component, causing expansion to fails. e.g., `c:` `c:.` `c:..` `c:foo.md` Solution: For these cases, we can pass letter and colon to `path_full_dir_name`. Notably, `..` is included as well. if that relative path exists, it can be expanded correctly.
This commit is contained in:
@@ -2380,20 +2380,23 @@ static int path_to_absolute(const char *fname, char *buf, size_t len, int force)
|
|||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
p = strrchr(fname, '\\');
|
p = strrchr(fname, '\\');
|
||||||
}
|
}
|
||||||
|
if (p == NULL && ASCII_ISALPHA(fname[0]) && fname[1] == ':') {
|
||||||
|
p = fname + 1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (p == NULL && strcmp(fname, "..") == 0) {
|
if (p == NULL && strcmp(fname, "..") == 0) {
|
||||||
// Handle ".." without path separators.
|
// Handle ".." without path separators.
|
||||||
p = fname + 2;
|
p = fname + 2;
|
||||||
}
|
}
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
if (vim_ispathsep_nocolon(*p) && strcmp(p + 1, "..") == 0) {
|
if (vim_ispathsep(*p) && strcmp(p + 1, "..") == 0) {
|
||||||
// For "/path/dir/.." include the "/..".
|
// For "/path/dir/.." include the "/..".
|
||||||
p += 3;
|
p += 3;
|
||||||
}
|
}
|
||||||
assert(p >= fname);
|
assert(p >= fname);
|
||||||
memcpy(relative_directory, fname, (size_t)(p - fname + 1));
|
memcpy(relative_directory, fname, (size_t)(p - fname + 1));
|
||||||
relative_directory[p - fname + 1] = NUL;
|
relative_directory[p - fname + 1] = NUL;
|
||||||
end_of_path = (vim_ispathsep_nocolon(*p) ? p + 1 : p);
|
end_of_path = (vim_ispathsep(*p) ? p + 1 : p);
|
||||||
} else {
|
} else {
|
||||||
relative_directory[0] = NUL;
|
relative_directory[0] = NUL;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ local getcwd = n.fn.getcwd
|
|||||||
local command = n.command
|
local command = n.command
|
||||||
local write_file = t.write_file
|
local write_file = t.write_file
|
||||||
local is_os = t.is_os
|
local is_os = t.is_os
|
||||||
|
local chdir = n.fn.chdir
|
||||||
|
|
||||||
local function eq_slashconvert(expected, got)
|
local function eq_slashconvert(expected, got)
|
||||||
eq(t.fix_slashes(expected), t.fix_slashes(got))
|
eq(t.fix_slashes(expected), t.fix_slashes(got))
|
||||||
@@ -16,12 +17,15 @@ end
|
|||||||
describe('fnamemodify()', function()
|
describe('fnamemodify()', function()
|
||||||
setup(function()
|
setup(function()
|
||||||
write_file('Xtest-fnamemodify.txt', [[foobar]])
|
write_file('Xtest-fnamemodify.txt', [[foobar]])
|
||||||
|
t.mkdir('foo')
|
||||||
|
write_file('foo/bar', [[bar]])
|
||||||
end)
|
end)
|
||||||
|
|
||||||
before_each(clear)
|
before_each(clear)
|
||||||
|
|
||||||
teardown(function()
|
teardown(function()
|
||||||
os.remove('Xtest-fnamemodify.txt')
|
os.remove('Xtest-fnamemodify.txt')
|
||||||
|
n.rmdir('foo')
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('handles the root path', function()
|
it('handles the root path', function()
|
||||||
@@ -37,6 +41,19 @@ describe('fnamemodify()', function()
|
|||||||
eq(root, fnamemodify([[\]], ':p'))
|
eq(root, fnamemodify([[\]], ':p'))
|
||||||
eq(root, fnamemodify([[/]], ':p:h'))
|
eq(root, fnamemodify([[/]], ':p:h'))
|
||||||
eq(root, fnamemodify([[/]], ':p'))
|
eq(root, fnamemodify([[/]], ':p'))
|
||||||
|
|
||||||
|
local letter_colon = root:sub(1, 2)
|
||||||
|
local old_dir = getcwd() .. '/'
|
||||||
|
local foo_dir = old_dir .. 'foo/'
|
||||||
|
eq(old_dir, fnamemodify(letter_colon, ':p'))
|
||||||
|
eq(old_dir, fnamemodify(letter_colon .. '.', ':p'))
|
||||||
|
eq(old_dir, fnamemodify(letter_colon .. './', ':p'))
|
||||||
|
eq(foo_dir, fnamemodify(letter_colon .. './foo', ':p'))
|
||||||
|
eq(foo_dir, fnamemodify(letter_colon .. 'foo', ':p'))
|
||||||
|
chdir('foo')
|
||||||
|
eq(old_dir, fnamemodify(letter_colon .. '..', ':p'))
|
||||||
|
eq(old_dir, fnamemodify(letter_colon .. '../', ':p'))
|
||||||
|
eq(foo_dir .. 'bar', fnamemodify(letter_colon .. 'bar', ':p'))
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user