changeset 11032:516391d8865f v8.0.0405

patch 8.0.0405: v:progpath may become invalid after :cd commit https://github.com/vim/vim/commit/08cab9608781c975b4acbad875862b842b29258d Author: Bram Moolenaar <Bram@vim.org> 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.
author Christian Brabandt <cb@256bit.org>
date Sat, 04 Mar 2017 14:45:05 +0100
parents 4dbc86032a4c
children b4517d047b29
files runtime/doc/eval.txt src/main.c src/testdir/test_startup.vim src/version.c
diffstat 4 files changed, 50 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- 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*
--- 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)
 
 /*
--- 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
--- 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,