diff options
-rw-r--r-- | src/nvim/buffer.c | 2 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 8 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 31 | ||||
-rw-r--r-- | src/nvim/file_search.c | 59 | ||||
-rw-r--r-- | src/nvim/memline.c | 11 | ||||
-rw-r--r-- | src/nvim/os/env.c | 22 | ||||
-rw-r--r-- | src/nvim/path.c | 3 | ||||
-rw-r--r-- | src/nvim/quickfix.c | 7 | ||||
-rw-r--r-- | src/nvim/spell.c | 22 | ||||
-rw-r--r-- | src/nvim/spellfile.c | 8 | ||||
-rw-r--r-- | src/nvim/tag.c | 23 | ||||
-rw-r--r-- | src/nvim/testdir/Makefile | 1 | ||||
-rw-r--r-- | src/nvim/testdir/runtest.vim | 3 | ||||
-rw-r--r-- | src/nvim/testdir/setup.vim | 11 | ||||
-rw-r--r-- | src/nvim/testdir/test_alot.vim | 1 | ||||
-rw-r--r-- | src/nvim/testdir/test_cd.vim | 13 | ||||
-rw-r--r-- | src/nvim/testdir/test_windows_home.vim | 121 |
17 files changed, 275 insertions, 71 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 4152c16588..a8d29a3a53 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -4420,7 +4420,7 @@ do_arg_all ( if (i < alist->al_ga.ga_len && (AARGLIST(alist)[i].ae_fnum == buf->b_fnum || path_full_compare(alist_name(&AARGLIST(alist)[i]), - buf->b_ffname, TRUE) & kEqualFiles)) { + buf->b_ffname, true) & kEqualFiles)) { int weight = 1; if (old_curtab == curtab) { diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 3c6a8b1074..176df58fb9 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -4977,7 +4977,8 @@ void fix_help_buffer(void) while (*p != NUL) { copy_option_part(&p, NameBuff, MAXPATHL, ","); rt = (char_u *)vim_getenv("VIMRUNTIME"); - if (path_full_compare(rt, NameBuff, FALSE) != kEqualFiles) { + if (rt != NULL + && path_full_compare(rt, NameBuff, false) != kEqualFiles) { int fcount; char_u **fnames; FILE *fd; @@ -5197,8 +5198,9 @@ static void helptags_one(char_u *dir, char_u *ext, char_u *tagfname, * add the "help-tags" tag. */ ga_init(&ga, (int)sizeof(char_u *), 100); - if (add_help_tags || path_full_compare((char_u *)"$VIMRUNTIME/doc", - dir, FALSE) == kEqualFiles) { + if (add_help_tags + || path_full_compare((char_u *)"$VIMRUNTIME/doc", + dir, false) == kEqualFiles) { s = xmalloc(18 + STRLEN(tagfname)); sprintf((char *)s, "help-tags\t%s\t1\n", tagfname); GA_APPEND(char_u *, &ga, s); diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 775d002e58..fd11acff84 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -5062,38 +5062,33 @@ static void * call_user_expand_func(user_expand_func_T user_expand_func, */ static int ExpandUserDefined(expand_T *xp, regmatch_T *regmatch, int *num_file, char_u ***file) { - char_u *retstr; - char_u *s; char_u *e; - char_u keep; garray_T ga; - retstr = call_user_expand_func((user_expand_func_T)call_func_retstr, xp, - num_file, file); + char_u *const retstr = call_user_expand_func( + (user_expand_func_T)call_func_retstr, xp, num_file, file); if (retstr == NULL) { return FAIL; } ga_init(&ga, (int)sizeof(char *), 3); - for (s = retstr; *s != NUL; s = e) { + for (char_u *s = retstr; *s != NUL; s = e) { e = vim_strchr(s, '\n'); if (e == NULL) e = s + STRLEN(s); - keep = *e; - *e = 0; + const int keep = *e; + *e = NUL; - if (xp->xp_pattern[0] && vim_regexec(regmatch, s, (colnr_T)0) == 0) { - *e = keep; - if (*e != NUL) - ++e; - continue; + const bool skip = xp->xp_pattern[0] + && vim_regexec(regmatch, s, (colnr_T)0) == 0; + *e = keep; + if (!skip) { + GA_APPEND(char_u *, &ga, vim_strnsave(s, (int)(e - s))); } - GA_APPEND(char_u *, &ga, vim_strnsave(s, (int)(e - s))); - - *e = keep; - if (*e != NUL) - ++e; + if (*e != NUL) { + e++; + } } xfree(retstr); *file = ga.ga_data; diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index 5b17b58781..6c1a2f6d7b 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -577,7 +577,7 @@ char_u *vim_findfile(void *search_ctx_arg) char_u *file_path; char_u *rest_of_wildcards; char_u *path_end = NULL; - ff_stack_T *stackp; + ff_stack_T *stackp = NULL; size_t len; char_u *p; char_u *suf; @@ -683,28 +683,40 @@ char_u *vim_findfile(void *search_ctx_arg) dirptrs[0] = file_path; dirptrs[1] = NULL; - /* if we have a start dir copy it in */ + // if we have a start dir copy it in if (!vim_isAbsName(stackp->ffs_fix_path) && search_ctx->ffsc_start_dir) { + if (STRLEN(search_ctx->ffsc_start_dir) + 1 >= MAXPATHL) { + goto fail; + } STRCPY(file_path, search_ctx->ffsc_start_dir); - add_pathsep((char *)file_path); + if (!add_pathsep((char *)file_path)) { + goto fail; + } } - /* append the fix part of the search path */ + // append the fix part of the search path + if (STRLEN(file_path) + STRLEN(stackp->ffs_fix_path) + 1 >= MAXPATHL) { + goto fail; + } STRCAT(file_path, stackp->ffs_fix_path); - add_pathsep((char *)file_path); + if (!add_pathsep((char *)file_path)) { + goto fail; + } rest_of_wildcards = stackp->ffs_wc_path; if (*rest_of_wildcards != NUL) { len = STRLEN(file_path); if (STRNCMP(rest_of_wildcards, "**", 2) == 0) { - /* pointer to the restrict byte - * The restrict byte is not a character! - */ + // pointer to the restrict byte + // The restrict byte is not a character! p = rest_of_wildcards + 2; if (*p > 0) { (*p)--; + if (len + 1 >= MAXPATHL) { + goto fail; + } file_path[len++] = '*'; } @@ -729,8 +741,12 @@ char_u *vim_findfile(void *search_ctx_arg) * on the stack again for further search. */ while (*rest_of_wildcards - && !vim_ispathsep(*rest_of_wildcards)) + && !vim_ispathsep(*rest_of_wildcards)) { + if (len + 1 >= MAXPATHL) { + goto fail; + } file_path[len++] = *rest_of_wildcards++; + } file_path[len] = NUL; if (vim_ispathsep(*rest_of_wildcards)) @@ -773,10 +789,15 @@ char_u *vim_findfile(void *search_ctx_arg) && !os_isdir(stackp->ffs_filearray[i])) continue; /* not a directory */ - /* prepare the filename to be checked for existence - * below */ + // prepare the filename to be checked for existence below + if (STRLEN(stackp->ffs_filearray[i]) + 1 + + STRLEN(search_ctx->ffsc_file_to_search) >= MAXPATHL) { + goto fail; + } STRCPY(file_path, stackp->ffs_filearray[i]); - add_pathsep((char *)file_path); + if (!add_pathsep((char *)file_path)) { + goto fail; + } STRCAT(file_path, search_ctx->ffsc_file_to_search); /* @@ -924,8 +945,14 @@ char_u *vim_findfile(void *search_ctx_arg) if (*search_ctx->ffsc_start_dir == 0) break; + if (STRLEN(search_ctx->ffsc_start_dir) + 1 + + STRLEN(search_ctx->ffsc_fix_path) >= MAXPATHL) { + goto fail; + } STRCPY(file_path, search_ctx->ffsc_start_dir); - add_pathsep((char *)file_path); + if (!add_pathsep((char *)file_path)) { + goto fail; + } STRCAT(file_path, search_ctx->ffsc_fix_path); /* create a new stack entry */ @@ -936,6 +963,8 @@ char_u *vim_findfile(void *search_ctx_arg) break; } +fail: + ff_free_stack_element(stackp); xfree(file_path); return NULL; } @@ -1194,6 +1223,10 @@ static ff_stack_T *ff_pop(ff_search_ctx_T *search_ctx) */ static void ff_free_stack_element(ff_stack_T *stack_ptr) { + if (stack_ptr == NULL) { + return; + } + /* free handles possible NULL pointers */ xfree(stack_ptr->ffs_fix_path); xfree(stack_ptr->ffs_wc_path); diff --git a/src/nvim/memline.c b/src/nvim/memline.c index fc9a1e8271..84ceaf0973 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -1365,11 +1365,11 @@ recover_names ( */ if (curbuf->b_ml.ml_mfp != NULL && (p = curbuf->b_ml.ml_mfp->mf_fname) != NULL) { - for (int i = 0; i < num_files; ++i) - if (path_full_compare(p, files[i], TRUE) & kEqualFiles) { - /* Remove the name from files[i]. Move further entries - * down. When the array becomes empty free it here, since - * FreeWild() won't be called below. */ + for (int i = 0; i < num_files; i++) { + if (path_full_compare(p, files[i], true) & kEqualFiles) { + // Remove the name from files[i]. Move further entries + // down. When the array becomes empty free it here, since + // FreeWild() won't be called below. xfree(files[i]); if (--num_files == 0) xfree(files); @@ -1377,6 +1377,7 @@ recover_names ( for (; i < num_files; ++i) files[i] = files[i + 1]; } + } } if (nr > 0) { file_count += num_files; diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c index 0df857352b..6997156d4c 100644 --- a/src/nvim/os/env.c +++ b/src/nvim/os/env.c @@ -196,16 +196,19 @@ void init_homedir(void) const char *homedrive = os_getenv("HOMEDRIVE"); const char *homepath = os_getenv("HOMEPATH"); if (homepath == NULL) { - homepath = "\\"; + homepath = "\\"; } - if (homedrive != NULL && strlen(homedrive) + strlen(homepath) < MAXPATHL) { + if (homedrive != NULL + && strlen(homedrive) + strlen(homepath) < MAXPATHL) { snprintf(os_buf, MAXPATHL, "%s%s", homedrive, homepath); if (os_buf[0] != NUL) { var = os_buf; - vim_setenv("HOME", os_buf); } } } + if (var == NULL) { + var = os_getenv("USERPROFILE"); + } #endif if (var != NULL) { @@ -608,6 +611,12 @@ char *vim_getenv(const char *name) return xstrdup(kos_env_path); } +#ifdef WIN32 + if (strcmp(name, "HOME") == 0) { + return xstrdup(homedir); + } +#endif + bool vimruntime = (strcmp(name, "VIMRUNTIME") == 0); if (!vimruntime && strcmp(name, "VIM") != 0) { return NULL; @@ -758,7 +767,12 @@ size_t home_replace(const buf_T *const buf, const char_u *src, dirlen = strlen(homedir); } - const char *const homedir_env = os_getenv("HOME"); + const char *homedir_env = os_getenv("HOME"); +#ifdef WIN32 + if (homedir_env == NULL) { + homedir_env = os_getenv("USERPROFILE"); + } +#endif char *homedir_env_mod = (char *)homedir_env; bool must_free = false; diff --git a/src/nvim/path.c b/src/nvim/path.c index d5c636ff08..0b90329686 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -52,7 +52,8 @@ /// @param s2 Second file name. /// @param checkname When both files don't exist, only compare their names. /// @return Enum of type FileComparison. @see FileComparison. -FileComparison path_full_compare(char_u *s1, char_u *s2, int checkname) +FileComparison path_full_compare(char_u *const s1, char_u *const s2, + const bool checkname) { assert(s1 && s2); char_u exp1[MAXPATHL]; diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 47760e1e70..664dd3e968 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -3603,15 +3603,16 @@ void ex_vimgrep(exarg_T *eap) goto theend; } - if (s != NULL && *s == NUL) { - /* Pattern is empty, use last search pattern. */ + if (s == NULL || *s == NUL) { + // Pattern is empty, use last search pattern. if (last_search_pat() == NULL) { EMSG(_(e_noprevre)); goto theend; } regmatch.regprog = vim_regcomp(last_search_pat(), RE_MAGIC); - } else + } else { regmatch.regprog = vim_regcomp(s, RE_MAGIC); + } if (regmatch.regprog == NULL) goto theend; diff --git a/src/nvim/spell.c b/src/nvim/spell.c index 0714eb3137..cb03257878 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -2043,9 +2043,11 @@ char_u *did_set_spelllang(win_T *wp) dont_use_region = true; // Check if we loaded this language before. - for (slang = first_lang; slang != NULL; slang = slang->sl_next) - if (path_full_compare(lang, slang->sl_fname, FALSE) == kEqualFiles) + for (slang = first_lang; slang != NULL; slang = slang->sl_next) { + if (path_full_compare(lang, slang->sl_fname, false) == kEqualFiles) { break; + } + } } else { filename = false; if (len > 3 && lang[len - 3] == '_') { @@ -2085,8 +2087,9 @@ char_u *did_set_spelllang(win_T *wp) } // Loop over the languages, there can be several files for "lang". - for (slang = first_lang; slang != NULL; slang = slang->sl_next) - if (filename ? path_full_compare(lang, slang->sl_fname, FALSE) == kEqualFiles + for (slang = first_lang; slang != NULL; slang = slang->sl_next) { + if (filename + ? path_full_compare(lang, slang->sl_fname, false) == kEqualFiles : STRICMP(lang, slang->sl_name) == 0) { region_mask = REGION_ALL; if (!filename && region != NULL) { @@ -2116,6 +2119,7 @@ char_u *did_set_spelllang(win_T *wp) nobreak = true; } } + } } // round 0: load int_wordlist, if possible. @@ -2137,17 +2141,21 @@ char_u *did_set_spelllang(win_T *wp) // If it was already found above then skip it. for (c = 0; c < ga.ga_len; ++c) { p = LANGP_ENTRY(ga, c)->lp_slang->sl_fname; - if (p != NULL && path_full_compare(spf_name, p, FALSE) == kEqualFiles) + if (p != NULL + && path_full_compare(spf_name, p, false) == kEqualFiles) { break; + } } if (c < ga.ga_len) continue; } // Check if it was loaded already. - for (slang = first_lang; slang != NULL; slang = slang->sl_next) - if (path_full_compare(spf_name, slang->sl_fname, FALSE) == kEqualFiles) + for (slang = first_lang; slang != NULL; slang = slang->sl_next) { + if (path_full_compare(spf_name, slang->sl_fname, false) == kEqualFiles) { break; + } + } if (slang == NULL) { // Not loaded, try loading it now. The language name includes the // region name, the region is ignored otherwise. for int_wordlist diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index 69fa95107e..6578c7d66c 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -1786,7 +1786,7 @@ spell_reload_one ( bool didit = false; for (slang = first_lang; slang != NULL; slang = slang->sl_next) { - if (path_full_compare(fname, slang->sl_fname, FALSE) == kEqualFiles) { + if (path_full_compare(fname, slang->sl_fname, false) == kEqualFiles) { slang_clear(slang); if (spell_load_file(fname, NULL, slang, false) == NULL) // reloading failed, clear the language @@ -4714,9 +4714,11 @@ static void spell_make_sugfile(spellinfo_T *spin, char_u *wfname) // pointer-linked version of the trie. And it avoids having two versions // of the code for the soundfolding stuff. // It might have been done already by spell_reload_one(). - for (slang = first_lang; slang != NULL; slang = slang->sl_next) - if (path_full_compare(wfname, slang->sl_fname, FALSE) == kEqualFiles) + for (slang = first_lang; slang != NULL; slang = slang->sl_next) { + if (path_full_compare(wfname, slang->sl_fname, false) == kEqualFiles) { break; + } + } if (slang == NULL) { spell_message(spin, (char_u *)_("Reading back spell file...")); slang = spell_load_file(wfname, NULL, NULL, false); diff --git a/src/nvim/tag.c b/src/nvim/tag.c index beff89d191..c09a13edb1 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -2289,7 +2289,7 @@ static char_u *tag_full_fname(tagptrs_T *tagp) { int c = *tagp->fname_end; *tagp->fname_end = NUL; - char_u *fullname = expand_tag_fname(tagp->fname, tagp->tag_fname, FALSE); + char_u *fullname = expand_tag_fname(tagp->fname, tagp->tag_fname, false); *tagp->fname_end = c; return fullname; @@ -2363,8 +2363,8 @@ jumpto_tag ( * Expand file name, when needed (for environment variables). * If 'tagrelative' option set, may change file name. */ - fname = expand_tag_fname(fname, tagp.tag_fname, TRUE); - tofree_fname = fname; /* free() it later */ + fname = expand_tag_fname(fname, tagp.tag_fname, true); + tofree_fname = fname; // free() it later /* * Check if the file with the tag exists before abandoning the current @@ -2615,13 +2615,12 @@ erret: return retval; } -/* - * If "expand" is TRUE, expand wildcards in fname. - * If 'tagrelative' option set, change fname (name of file containing tag) - * according to tag_fname (name of tag file containing fname). - * Returns a pointer to allocated memory. - */ -static char_u *expand_tag_fname(char_u *fname, char_u *tag_fname, int expand) +// If "expand" is true, expand wildcards in fname. +// If 'tagrelative' option set, change fname (name of file containing tag) +// according to tag_fname (name of tag file containing fname). +// Returns a pointer to allocated memory. +static char_u *expand_tag_fname(char_u *fname, char_u *const tag_fname, + const bool expand) { char_u *p; char_u *expanded_fname = NULL; @@ -2676,8 +2675,8 @@ static int test_for_current(char_u *fname, char_u *fname_end, char_u *tag_fname, c = *fname_end; *fname_end = NUL; } - fullname = expand_tag_fname(fname, tag_fname, TRUE); - retval = (path_full_compare(fullname, buf_ffname, TRUE) & kEqualFiles); + fullname = expand_tag_fname(fname, tag_fname, true); + retval = (path_full_compare(fullname, buf_ffname, true) & kEqualFiles); xfree(fullname); *fname_end = c; } diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index 87d7ff5bad..0379235ec0 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -116,6 +116,7 @@ NEW_TESTS ?= \ test_visual.res \ test_winbuf_close.res \ test_window_id.res \ + test_windows_home.res \ test_wordcount.res \ test_writefile.res \ test_alot_latin.res \ diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim index f2cd84f556..8014b76af7 100644 --- a/src/nvim/testdir/runtest.vim +++ b/src/nvim/testdir/runtest.vim @@ -173,6 +173,9 @@ func FinishTesting() " Don't write viminfo on exit. set viminfo= + " Clean up files created by setup.vim + call delete('XfakeHOME', 'rf') + if s:fail == 0 " Success, create the .res file so that make knows it's done. exe 'split ' . fnamemodify(g:testname, ':r') . '.res' diff --git a/src/nvim/testdir/setup.vim b/src/nvim/testdir/setup.vim index aac9fefef4..f3cc7da70f 100644 --- a/src/nvim/testdir/setup.vim +++ b/src/nvim/testdir/setup.vim @@ -1,5 +1,11 @@ " Common preparations for running tests. +" Only load this once. +if exists('s:did_load') + finish +endif +let s:did_load = 1 + " Align Nvim defaults to Vim. set sidescroll=0 set directory^=. @@ -16,7 +22,10 @@ set rtp=$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after let &packpath = &rtp " Make sure $HOME does not get read or written. -let $HOME = '/does/not/exist' +let $HOME = expand(getcwd() . '/XfakeHOME') +if !isdirectory($HOME) + call mkdir($HOME) +endif " Use default shell on Windows to avoid segfault, caused by TUI if has('win32') diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index 1a70ac152f..d026221dac 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -2,6 +2,7 @@ " This makes testing go faster, since Vim doesn't need to restart. source test_assign.vim +source test_cd.vim source test_changedtick.vim source test_cursor_func.vim source test_ex_undo.vim diff --git a/src/nvim/testdir/test_cd.vim b/src/nvim/testdir/test_cd.vim new file mode 100644 index 0000000000..e573419bd0 --- /dev/null +++ b/src/nvim/testdir/test_cd.vim @@ -0,0 +1,13 @@ +" Test for :cd + +func Test_cd_large_path() + " This used to crash with a heap write overflow. + call assert_fails('cd ' . repeat('x', 5000), 'E472:') +endfunc + +func Test_cd_up_and_down() + let path = getcwd() + cd .. + exe 'cd ' . path + call assert_equal(path, getcwd()) +endfunc diff --git a/src/nvim/testdir/test_windows_home.vim b/src/nvim/testdir/test_windows_home.vim new file mode 100644 index 0000000000..bbcbf96050 --- /dev/null +++ b/src/nvim/testdir/test_windows_home.vim @@ -0,0 +1,121 @@ +" Test for $HOME on Windows. + +if !has('win32') + finish +endif + +let s:env = {} + +func s:restore_env() + for i in keys(s:env) + exe 'let ' . i . '=s:env["' . i . '"]' + endfor +endfunc + +func s:save_env(...) + for i in a:000 + exe 'let s:env["' . i . '"]=' . i + endfor +endfunc + +func s:unlet_env(...) + for i in a:000 + exe 'let ' . i . '=""' + endfor +endfunc + +func CheckHomeIsMissingFromSubprocessEnvironment() + silent! let out = system('set') + let env = filter(split(out, "\n"), 'v:val=~"^HOME="') + call assert_equal(0, len(env)) +endfunc + +func CheckHomeIsInSubprocessEnvironment(exp) + silent! let out = system('set') + let env = filter(split(out, "\n"), 'v:val=~"^HOME="') + let home = len(env) == 0 ? "" : substitute(env[0], '[^=]\+=', '', '') + call assert_equal(a:exp, home) +endfunc + +func CheckHome(exp, ...) + call assert_equal(a:exp, $HOME) + call assert_equal(a:exp, expand('~', ':p')) + if !a:0 + call CheckHomeIsMissingFromSubprocessEnvironment() + else + call CheckHomeIsInSubprocessEnvironment(a:1) + endif +endfunc + +func Test_WindowsHome() + command! -nargs=* SaveEnv call <SID>save_env(<f-args>) + command! -nargs=* RestoreEnv call <SID>restore_env() + command! -nargs=* UnletEnv call <SID>unlet_env(<f-args>) + set noshellslash + + let save_home = $HOME + SaveEnv $USERPROFILE $HOMEDRIVE $HOMEPATH + try + " Normal behavior: use $HOMEDRIVE and $HOMEPATH, ignore $USERPROFILE + let $USERPROFILE = 'unused' + let $HOMEDRIVE = 'C:' + let $HOMEPATH = '\foobar' + let $HOME = '' " Force recomputing "homedir" + call CheckHome('C:\foobar') + + " Same, but with $HOMEPATH not set + UnletEnv $HOMEPATH + let $HOME = '' " Force recomputing "homedir" + call CheckHome('C:\') + + " Use $USERPROFILE if $HOMEPATH and $HOMEDRIVE are empty + UnletEnv $HOMEDRIVE $HOMEPATH + let $USERPROFILE = 'C:\foo' + let $HOME = '' " Force recomputing "homedir" + call CheckHome('C:\foo') + + " If $HOME is set the others don't matter + let $HOME = 'C:\bar' + let $USERPROFILE = 'unused' + let $HOMEDRIVE = 'unused' + let $HOMEPATH = 'unused' + call CheckHome('C:\bar', 'C:\bar') + + " If $HOME contains %USERPROFILE% it is expanded + let $USERPROFILE = 'C:\foo' + let $HOME = '%USERPROFILE%\bar' + let $HOMEDRIVE = 'unused' + let $HOMEPATH = 'unused' + " call CheckHome('C:\foo\bar', '%USERPROFILE%\bar') + + " Invalid $HOME is kept + let $USERPROFILE = 'C:\foo' + let $HOME = '%USERPROFILE' + let $HOMEDRIVE = 'unused' + let $HOMEPATH = 'unused' + call CheckHome('%USERPROFILE', '%USERPROFILE') + + " %USERPROFILE% not at start of $HOME is not expanded + let $USERPROFILE = 'unused' + let $HOME = 'C:\%USERPROFILE%' + let $HOMEDRIVE = 'unused' + let $HOMEPATH = 'unused' + call CheckHome('C:\%USERPROFILE%', 'C:\%USERPROFILE%') + + if has('channel') + RestoreEnv + let $HOME = save_home + let env = '' + let job = job_start('cmd /c set', {'out_cb': {ch,x->[env,execute('let env=x')]}}) + sleep 1 + let env = filter(split(env, "\n"), 'v:val=="HOME"') + let home = len(env) == 0 ? "" : env[0] + call assert_equal('', home) + endif + finally + RestoreEnv + delcommand SaveEnv + delcommand RestoreEnv + delcommand UnletEnv + endtry +endfunc |