# HG changeset patch # User Christian Brabandt # Date 1488635105 -3600 # Node ID 516391d8865fd6b7a740fe8fe553709f736030ff # Parent 4dbc86032a4c690ee7361bfe957fa81e38370c11 patch 8.0.0405: v:progpath may become invalid after :cd commit https://github.com/vim/vim/commit/08cab9608781c975b4acbad875862b842b29258d Author: Bram Moolenaar Date: Sat Mar 4 14:37:18 2017 +0100 patch 8.0.0405: v:progpath may become invalid after :cd Problem: v:progpath may become invalid after ":cd". Solution: Turn v:progpath into a full path if needed. diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1789,8 +1789,11 @@ v:progpath Contains the command with whi |--remote-expr|. To get the full path use: > echo exepath(v:progpath) -< NOTE: This does not work when the command is a relative path - and the current directory has changed. +< If the path is relative it will be expanded to the full path, + so that it still works after `:cd`. Thus starting "./vim" + results in "/home/user/path/to/vim/src/vim". + On MS-Windows the executable may be called "vim.exe", but the + ".exe" is not added to v:progpath. Read-only. *v:register* *register-variable* diff --git a/src/main.c b/src/main.c --- a/src/main.c +++ b/src/main.c @@ -57,6 +57,9 @@ static void main_start_gui(void); # if defined(HAS_SWAP_EXISTS_ACTION) static void check_swap_exists_action(void); # endif +# ifdef FEAT_EVAL +static void set_progpath(char_u *argv0); +# endif # if defined(FEAT_CLIENTSERVER) || defined(PROTO) static void exec_on_server(mparm_T *parmp); static void prepare_server(mparm_T *parmp); @@ -1694,7 +1697,7 @@ parse_command_name(mparm_T *parmp) #ifdef FEAT_EVAL set_vim_var_string(VV_PROGNAME, initstr, -1); - set_vim_var_string(VV_PROGPATH, (char_u *)parmp->argv[0], -1); + set_progpath((char_u *)parmp->argv[0]); #endif if (TOLOWER_ASC(initstr[0]) == 'r') @@ -3417,7 +3420,7 @@ check_swap_exists_action(void) } #endif -#endif +#endif /* NO_VIM_MAIN */ #if defined(STARTUPTIME) || defined(PROTO) static void time_diff(struct timeval *then, struct timeval *now); @@ -3525,6 +3528,30 @@ time_msg( #endif +#ifndef NO_VIM_MAIN + static void +set_progpath(char_u *argv0) +{ + char_u *val = argv0; + char_u buf[MAXPATHL]; + + /* A relative path containing a "/" will become invalid when using ":cd", + * turn it into a full path. + * On MS-Windows "vim.exe" is found in the current directory, thus also do + * it when there is no path and the file exists. */ + if ( !mch_isFullName(argv0) +# ifdef WIN32 + && mch_can_exe(argv0, NULL, TRUE) +# else + && gettail(argv0) != argv0 +# endif + && vim_FullName(argv0, buf, MAXPATHL, TRUE) != FAIL) + val = buf; + set_vim_var_string(VV_PROGPATH, val, -1); +} + +#endif /* NO_VIM_MAIN */ + #if (defined(FEAT_CLIENTSERVER) && !defined(NO_VIM_MAIN)) || defined(PROTO) /* diff --git a/src/testdir/test_startup.vim b/src/testdir/test_startup.vim --- a/src/testdir/test_startup.vim +++ b/src/testdir/test_startup.vim @@ -183,3 +183,17 @@ func Test_read_stdin() endif call delete('Xtestout') endfunc + +func Test_progpath() + " Tests normally run with "./vim" or "../vim", these must have been expanded + " to a full path. + if has('unix') + call assert_equal('/', v:progpath[0]) + elseif has('win32') + call assert_equal(':', v:progpath[1]) + call assert_match('[/\\]', v:progpath[2]) + endif + + " Only expect "vim" to appear in v:progname. + call assert_match('vim\c', v:progname) +endfunc diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -765,6 +765,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 405, +/**/ 404, /**/ 403,