mirror of
https://github.com/neovim/neovim.git
synced 2025-09-07 20:08:17 +00:00
Use uv_os_homedir and current directory as backup when $HOME is not set (#13657)
Close https://github.com/neovim/neovim/issues/8614 Use uv_os_homedir and current directory as backup if HOME env is not set. Allocate homedir only if var is not NULL.
This commit is contained in:
@@ -394,13 +394,21 @@ void os_get_hostname(char *hostname, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// To get the "real" home directory:
|
/// To get the "real" home directory:
|
||||||
/// - get value of $HOME
|
/// 1. get value of $HOME
|
||||||
|
/// 2. if $HOME is not set, try the following
|
||||||
|
/// For Windows:
|
||||||
|
/// 1. assemble homedir using HOMEDRIVE and HOMEPATH
|
||||||
|
/// 2. try os_homedir()
|
||||||
|
/// 3. resolve a direct reference to another system variable
|
||||||
|
/// 4. guess C drive
|
||||||
/// For Unix:
|
/// For Unix:
|
||||||
/// - go to that directory
|
/// 1. try os_homedir()
|
||||||
/// - do os_dirname() to get the real name of that directory.
|
/// 2. go to that directory
|
||||||
/// This also works with mounts and links.
|
/// This also works with mounts and links.
|
||||||
/// Don't do this for Windows, it will change the "current dir" for a drive.
|
/// Don't do this for Windows, it will change the "current dir" for a drive.
|
||||||
|
/// 3. fall back to current working directory as a last resort
|
||||||
static char *homedir = NULL;
|
static char *homedir = NULL;
|
||||||
|
static char *os_homedir(void);
|
||||||
|
|
||||||
void init_homedir(void)
|
void init_homedir(void)
|
||||||
{
|
{
|
||||||
@@ -430,7 +438,7 @@ void init_homedir(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (var == NULL) {
|
if (var == NULL) {
|
||||||
var = os_getenv("USERPROFILE");
|
var = os_homedir();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Weird but true: $HOME may contain an indirect reference to another
|
// Weird but true: $HOME may contain an indirect reference to another
|
||||||
@@ -440,6 +448,7 @@ void init_homedir(void)
|
|||||||
const char *p = strchr(var + 1, '%');
|
const char *p = strchr(var + 1, '%');
|
||||||
if (p != NULL) {
|
if (p != NULL) {
|
||||||
vim_snprintf(os_buf, (size_t)(p - var), "%s", var + 1);
|
vim_snprintf(os_buf, (size_t)(p - var), "%s", var + 1);
|
||||||
|
var = NULL;
|
||||||
const char *exp = os_getenv(os_buf);
|
const char *exp = os_getenv(os_buf);
|
||||||
if (exp != NULL && *exp != NUL
|
if (exp != NULL && *exp != NUL
|
||||||
&& STRLEN(exp) + STRLEN(p) < MAXPATHL) {
|
&& STRLEN(exp) + STRLEN(p) < MAXPATHL) {
|
||||||
@@ -458,8 +467,12 @@ void init_homedir(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (var != NULL) {
|
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
|
if (var == NULL) {
|
||||||
|
var = os_homedir();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (var != NULL) {
|
||||||
// Change to the directory and get the actual path. This resolves
|
// Change to the directory and get the actual path. This resolves
|
||||||
// links. Don't do it when we can't return.
|
// links. Don't do it when we can't return.
|
||||||
if (os_dirname((char_u *)os_buf, MAXPATHL) == OK && os_chdir(os_buf) == 0) {
|
if (os_dirname((char_u *)os_buf, MAXPATHL) == OK && os_chdir(os_buf) == 0) {
|
||||||
@@ -470,11 +483,37 @@ void init_homedir(void)
|
|||||||
EMSG(_(e_prev_dir));
|
EMSG(_(e_prev_dir));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to current working directory if home is not found
|
||||||
|
if ((var == NULL || *var == NUL)
|
||||||
|
&& os_dirname((char_u *)os_buf, sizeof(os_buf)) == OK) {
|
||||||
|
var = os_buf;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (var != NULL) {
|
||||||
homedir = xstrdup(var);
|
homedir = xstrdup(var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char homedir_buf[MAXPATHL];
|
||||||
|
|
||||||
|
static char *os_homedir(void)
|
||||||
|
{
|
||||||
|
homedir_buf[0] = NUL;
|
||||||
|
size_t homedir_size = MAXPATHL;
|
||||||
|
uv_mutex_lock(&mutex);
|
||||||
|
// http://docs.libuv.org/en/v1.x/misc.html#c.uv_os_homedir
|
||||||
|
int ret_value = uv_os_homedir(homedir_buf, &homedir_size);
|
||||||
|
uv_mutex_unlock(&mutex);
|
||||||
|
if (ret_value == 0 && homedir_size < MAXPATHL) {
|
||||||
|
return homedir_buf;
|
||||||
|
}
|
||||||
|
ELOG("uv_os_homedir() failed %d: %s", ret_value, os_strerror(ret_value));
|
||||||
|
homedir_buf[0] = NUL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(EXITFREE)
|
#if defined(EXITFREE)
|
||||||
|
|
||||||
void free_homedir(void)
|
void free_homedir(void)
|
||||||
|
@@ -3,6 +3,11 @@ local clear = helpers.clear
|
|||||||
local eq = helpers.eq
|
local eq = helpers.eq
|
||||||
local environ = helpers.funcs.environ
|
local environ = helpers.funcs.environ
|
||||||
local exists = helpers.funcs.exists
|
local exists = helpers.funcs.exists
|
||||||
|
local system = helpers.funcs.system
|
||||||
|
local nvim_prog = helpers.nvim_prog
|
||||||
|
local command = helpers.command
|
||||||
|
local eval = helpers.eval
|
||||||
|
local setenv = helpers.funcs.setenv
|
||||||
|
|
||||||
describe('environment variables', function()
|
describe('environment variables', function()
|
||||||
it('environ() handles empty env variable', function()
|
it('environ() handles empty env variable', function()
|
||||||
@@ -17,3 +22,59 @@ describe('environment variables', function()
|
|||||||
eq(0, exists('$DOES_NOT_EXIST'))
|
eq(0, exists('$DOES_NOT_EXIST'))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
describe('empty $HOME', function()
|
||||||
|
local original_home = os.getenv('HOME')
|
||||||
|
|
||||||
|
-- recover $HOME after each test
|
||||||
|
after_each(function()
|
||||||
|
if original_home ~= nil then
|
||||||
|
setenv('HOME', original_home)
|
||||||
|
end
|
||||||
|
os.remove('test_empty_home')
|
||||||
|
os.remove('./~')
|
||||||
|
end)
|
||||||
|
|
||||||
|
local function tilde_in_cwd()
|
||||||
|
-- get files in cwd
|
||||||
|
command("let test_empty_home_cwd_files = split(globpath('.', '*'), '\n')")
|
||||||
|
-- get the index of the file named '~'
|
||||||
|
command('let test_empty_home_tilde_index = index(test_empty_home_cwd_files, "./~")')
|
||||||
|
return eval('test_empty_home_tilde_index') ~= -1
|
||||||
|
end
|
||||||
|
|
||||||
|
local function write_and_test_tilde()
|
||||||
|
system({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--headless',
|
||||||
|
'-c', 'write test_empty_home', '+q'})
|
||||||
|
eq(false, tilde_in_cwd())
|
||||||
|
end
|
||||||
|
|
||||||
|
it("'~' folder not created in cwd if $HOME and related env not defined", function()
|
||||||
|
command("unlet $HOME")
|
||||||
|
write_and_test_tilde()
|
||||||
|
|
||||||
|
command("let $HOMEDRIVE='C:'")
|
||||||
|
command("let $USERPROFILE='C:\\'")
|
||||||
|
write_and_test_tilde()
|
||||||
|
|
||||||
|
command("unlet $HOMEDRIVE")
|
||||||
|
write_and_test_tilde()
|
||||||
|
|
||||||
|
command("unlet $USERPROFILE")
|
||||||
|
write_and_test_tilde()
|
||||||
|
|
||||||
|
command("let $HOME='%USERPROFILE%'")
|
||||||
|
command("let $USERPROFILE='C:\\'")
|
||||||
|
write_and_test_tilde()
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("'~' folder not created in cwd if writing a file with invalid $HOME", function()
|
||||||
|
setenv('HOME', '/path/does/not/exist')
|
||||||
|
write_and_test_tilde()
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("'~' folder not created in cwd if writing a file with $HOME=''", function()
|
||||||
|
command("let $HOME=''")
|
||||||
|
write_and_test_tilde()
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
Reference in New Issue
Block a user