changeset 12265:03e4be2e3d53 v8.0.1012

patch 8.0.1012: MS-Windows: problem with $HOME when is was set internally commit https://github.com/vim/vim/commit/48340b62e812dc9280f621a2eb6db76d43555c66 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Aug 29 22:08:53 2017 +0200 patch 8.0.1012: MS-Windows: problem with $HOME when is was set internally Problem: MS-Windows: Problem with $HOME when is was set internally. Solution: Only use the $HOME default internally. (Yasuhiro Matsumoto, closes #2013)
author Christian Brabandt <cb@256bit.org>
date Tue, 29 Aug 2017 22:15:05 +0200
parents 4ebb86735ae5
children f53e950a0414
files src/Makefile src/misc1.c src/testdir/Make_all.mak src/testdir/test_windows_home.vim src/version.c
diffstat 5 files changed, 169 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/src/Makefile
+++ b/src/Makefile
@@ -2278,6 +2278,7 @@ test_arglist \
 	test_visual \
 	test_window_cmd \
 	test_window_id \
+	test_windows_home \
 	test_writefile \
 	test_alot_latin \
 	test_alot_utf8 \
--- a/src/misc1.c
+++ b/src/misc1.c
@@ -3750,11 +3750,34 @@ init_homedir(void)
     var = mch_getenv((char_u *)"HOME");
 #endif
 
-    if (var != NULL && *var == NUL)	/* empty is same as not set */
-	var = NULL;
-
 #ifdef WIN3264
     /*
+     * Typically, $HOME is not defined on Windows, unless the user has
+     * specifically defined it for Vim's sake.  However, on Windows NT
+     * platforms, $HOMEDRIVE and $HOMEPATH are automatically defined for
+     * each user.  Try constructing $HOME from these.
+     */
+    if (var == NULL || *var == NULL)
+    {
+	char_u *homedrive, *homepath;
+
+	homedrive = mch_getenv((char_u *)"HOMEDRIVE");
+	homepath = mch_getenv((char_u *)"HOMEPATH");
+	if (homepath == NULL || *homepath == NUL)
+	    homepath = (char_u *)"\\";
+	if (homedrive != NULL
+			   && STRLEN(homedrive) + STRLEN(homepath) < MAXPATHL)
+	{
+	    sprintf((char *)NameBuff, "%s%s", homedrive, homepath);
+	    if (NameBuff[0] != NUL)
+		var = NameBuff;
+	}
+    }
+
+    if (var == NULL)
+	var = mch_getenv((char_u *)"USERPROFILE");
+
+    /*
      * Weird but true: $HOME may contain an indirect reference to another
      * variable, esp. "%USERPROFILE%".  Happens when $USERPROFILE isn't set
      * when $HOME is being set.
@@ -3774,40 +3797,14 @@ init_homedir(void)
 	    {
 		vim_snprintf((char *)NameBuff, MAXPATHL, "%s%s", exp, p + 1);
 		var = NameBuff;
-		/* Also set $HOME, it's needed for _viminfo. */
-		vim_setenv((char_u *)"HOME", NameBuff);
-	    }
-	}
-    }
-
-    /*
-     * Typically, $HOME is not defined on Windows, unless the user has
-     * specifically defined it for Vim's sake.  However, on Windows NT
-     * platforms, $HOMEDRIVE and $HOMEPATH are automatically defined for
-     * each user.  Try constructing $HOME from these.
-     */
-    if (var == NULL)
-    {
-	char_u *homedrive, *homepath;
-
-	homedrive = mch_getenv((char_u *)"HOMEDRIVE");
-	homepath = mch_getenv((char_u *)"HOMEPATH");
-	if (homepath == NULL || *homepath == NUL)
-	    homepath = (char_u *)"\\";
-	if (homedrive != NULL
-			   && STRLEN(homedrive) + STRLEN(homepath) < MAXPATHL)
-	{
-	    sprintf((char *)NameBuff, "%s%s", homedrive, homepath);
-	    if (NameBuff[0] != NUL)
-	    {
-		var = NameBuff;
-		/* Also set $HOME, it's needed for _viminfo. */
-		vim_setenv((char_u *)"HOME", NameBuff);
-	    }
-	}
-    }
-
-# if defined(FEAT_MBYTE)
+	    }
+	}
+    }
+
+    if (var != NULL && *var == NUL)	/* empty is same as not set */
+	var = NULL;
+
+# ifdef FEAT_MBYTE
     if (enc_utf8 && var != NULL)
     {
 	int	len;
@@ -3823,9 +3820,7 @@ init_homedir(void)
 	}
     }
 # endif
-#endif
-
-#if defined(MSWIN)
+
     /*
      * Default home dir is C:/
      * Best assumption we can make in such a situation.
@@ -3833,6 +3828,7 @@ init_homedir(void)
     if (var == NULL)
 	var = (char_u *)"C:/";
 #endif
+
     if (var != NULL)
     {
 #ifdef UNIX
@@ -4662,6 +4658,10 @@ home_replace(
 #else
     homedir_env_orig = homedir_env = mch_getenv((char_u *)"HOME");
 #endif
+#ifdef WIN3264
+    if (homedir_env == NULL)
+	homedir_env_orig = homedir_env = mch_getenv((char_u *)"USERPROFILE");
+#endif
     /* Empty is the same as not set. */
     if (homedir_env != NULL && *homedir_env == NUL)
 	homedir_env = NULL;
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -205,7 +205,8 @@ NEW_TESTS = test_arabic.res \
 	    test_writefile.res \
 	    test_alot_latin.res \
 	    test_alot_utf8.res \
-	    test_alot.res
+	    test_alot.res \
+	    test_windows_home.res
 
 
 # Explicit dependencies.
new file mode 100644
--- /dev/null
+++ b/src/testdir/test_windows_home.vim
@@ -0,0 +1,124 @@
+" 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:exp)
+  endif
+endfunc
+
+func TestWindowsHome()
+  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>)
+
+  SaveEnv $HOME $USERPROFILE $HOMEDRIVE $HOMEPATH
+  try
+    RestoreEnv
+    UnletEnv $HOME $USERPROFILE $HOMEPATH
+    let $HOMEDRIVE = 'C:'
+    call CheckHome('C:\')
+
+    RestoreEnv
+    UnletEnv $HOME $USERPROFILE
+    let $HOMEDRIVE = 'C:'
+    let $HOMEPATH = '\foobar'
+    call CheckHome('C:\foobar')
+
+    RestoreEnv
+    UnletEnv $HOME $HOMEDRIVE $HOMEPATH
+    let $USERPROFILE = 'C:\foo'
+    call CheckHome('C:\foo')
+
+    RestoreEnv
+    UnletEnv $HOME
+    let $USERPROFILE = 'C:\foo'
+    let $HOMEDRIVE = 'C:'
+    let $HOMEPATH = '\baz'
+    call CheckHome('C:\foo')
+
+    RestoreEnv
+    let $HOME = 'C:\bar'
+    let $USERPROFILE = 'C:\foo'
+    let $HOMEDRIVE = 'C:'
+    let $HOMEPATH = '\baz'
+    call CheckHome('C:\bar', 1)
+
+    RestoreEnv
+    let $HOME = '%USERPROFILE%\bar'
+    let $USERPROFILE = 'C:\foo'
+    let $HOMEDRIVE = 'C:'
+    let $HOMEPATH = '\baz'
+    call CheckHome('%USERPROFILE%\bar', 1)
+
+    RestoreEnv
+    let $HOME = '%USERPROFILE'
+    let $USERPROFILE = 'C:\foo'
+    let $HOMEDRIVE = 'C:'
+    let $HOMEPATH = '\baz'
+    call CheckHome('%USERPROFILE', 1)
+
+    RestoreEnv
+    let $HOME = 'C:\%USERPROFILE%'
+    let $USERPROFILE = 'C:\foo'
+    let $HOMEDRIVE = 'C:'
+    let $HOMEPATH = '\baz'
+    call CheckHome('C:\%USERPROFILE%', 1)
+
+    if has('channel')
+      RestoreEnv
+      UnletEnv $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
--- a/src/version.c
+++ b/src/version.c
@@ -770,6 +770,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1012,
+/**/
     1011,
 /**/
     1010,