Merge branch 'kb/mingw-set-home'
authorJunio C Hamano <gitster@pobox.com>
Fri, 19 Jul 2019 18:30:23 +0000 (11:30 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 19 Jul 2019 18:30:23 +0000 (11:30 -0700)
Windows port update.

* kb/mingw-set-home:
mingw: initialize HOME on startup

1  2 
compat/mingw.c
diff --combined compat/mingw.c
index 48917897710169fff29d93e5f1b5313cea871808,1047427cb559efc2f3c1d932f94e25d35da5d45d..d9913463be184fc508610c082f2ec1827898d12d
@@@ -1407,7 -1407,7 +1407,7 @@@ static pid_t mingw_spawnve_fd(const cha
        do_unset_environment_variables();
  
        /* Determine whether or not we are associated to a console */
 -      cons = CreateFile("CONOUT$", GENERIC_WRITE,
 +      cons = CreateFileW(L"CONOUT$", GENERIC_WRITE,
                        FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
                        FILE_ATTRIBUTE_NORMAL, NULL);
        if (cons == INVALID_HANDLE_VALUE) {
@@@ -1553,10 -1553,7 +1553,10 @@@ static int try_shell_exec(const char *c
        if (prog) {
                int exec_id;
                int argc = 0;
 -              const char **argv2;
 +#ifndef _MSC_VER
 +              const
 +#endif
 +              char **argv2;
                while (argv[argc]) argc++;
                ALLOC_ARRAY(argv2, argc + 1);
                argv2[0] = (char *)cmd; /* full path to the script file */
@@@ -1949,19 -1946,13 +1949,19 @@@ struct passwd *getpwuid(int uid
        static unsigned initialized;
        static char user_name[100];
        static struct passwd *p;
 +      wchar_t buf[100];
        DWORD len;
  
        if (initialized)
                return p;
  
 -      len = sizeof(user_name);
 -      if (!GetUserName(user_name, &len)) {
 +      len = ARRAY_SIZE(buf);
 +      if (!GetUserNameW(buf, &len)) {
 +              initialized = 1;
 +              return NULL;
 +      }
 +
 +      if (xwcstoutf(user_name, buf, sizeof(user_name)) < 0) {
                initialized = 1;
                return NULL;
        }
@@@ -2125,33 -2116,8 +2125,33 @@@ int mingw_raise(int sig
                        sigint_fn(SIGINT);
                return 0;
  
 +#if defined(_MSC_VER)
 +      case SIGILL:
 +      case SIGFPE:
 +      case SIGSEGV:
 +      case SIGTERM:
 +      case SIGBREAK:
 +      case SIGABRT:
 +      case SIGABRT_COMPAT:
 +              /*
 +               * The <signal.h> header in the MS C Runtime defines 8 signals
 +               * as being supported on the platform. Anything else causes an
 +               * "Invalid signal or error" (which in DEBUG builds causes the
 +               * Abort/Retry/Ignore dialog). We by-pass the CRT for things we
 +               * already know will fail.
 +               */
 +              return raise(sig);
 +      default:
 +              errno = EINVAL;
 +              return -1;
 +
 +#else
 +
        default:
                return raise(sig);
 +
 +#endif
 +
        }
  }
  
@@@ -2333,15 -2299,44 +2333,39 @@@ static void setup_windows_environment(v
        /* simulate TERM to enable auto-color (see color.c) */
        if (!getenv("TERM"))
                setenv("TERM", "cygwin", 1);
+       /* calculate HOME if not set */
+       if (!getenv("HOME")) {
+               /*
+                * try $HOMEDRIVE$HOMEPATH - the home share may be a network
+                * location, thus also check if the path exists (i.e. is not
+                * disconnected)
+                */
+               if ((tmp = getenv("HOMEDRIVE"))) {
+                       struct strbuf buf = STRBUF_INIT;
+                       strbuf_addstr(&buf, tmp);
+                       if ((tmp = getenv("HOMEPATH"))) {
+                               strbuf_addstr(&buf, tmp);
+                               if (is_directory(buf.buf))
+                                       setenv("HOME", buf.buf, 1);
+                               else
+                                       tmp = NULL; /* use $USERPROFILE */
+                       }
+                       strbuf_release(&buf);
+               }
+               /* use $USERPROFILE if the home share is not available */
+               if (!tmp && (tmp = getenv("USERPROFILE")))
+                       setenv("HOME", tmp, 1);
+       }
  }
  
 +#if !defined(_MSC_VER)
  /*
   * Disable MSVCRT command line wildcard expansion (__getmainargs called from
   * mingw startup code, see init.c in mingw runtime).
   */
  int _CRT_glob = 0;
 -
 -typedef struct {
 -      int newmode;
 -} _startupinfo;
 -
 -extern int __wgetmainargs(int *argc, wchar_t ***argv, wchar_t ***env, int glob,
 -              _startupinfo *si);
 +#endif
  
  static NORETURN void die_startup(void)
  {
@@@ -2419,40 -2414,21 +2443,40 @@@ static void maybe_redirect_std_handles(
                                  GENERIC_WRITE, FILE_FLAG_NO_BUFFERING);
  }
  
 -void mingw_startup(void)
 +#ifdef _MSC_VER
 +#ifdef _DEBUG
 +#include <crtdbg.h>
 +#endif
 +#endif
 +
 +/*
 + * We implement wmain() and compile with -municode, which would
 + * normally ignore main(), but we call the latter from the former
 + * so that we can handle non-ASCII command-line parameters
 + * appropriately.
 + *
 + * To be more compatible with the core git code, we convert
 + * argv into UTF8 and pass them directly to main().
 + */
 +int wmain(int argc, const wchar_t **wargv)
  {
 -      int i, maxlen, argc;
 -      char *buffer;
 -      wchar_t **wenv, **wargv;
 -      _startupinfo si;
 +      int i, maxlen, exit_status;
 +      char *buffer, **save;
 +      const char **argv;
  
        trace2_initialize_clock();
  
 -      maybe_redirect_std_handles();
 +#ifdef _MSC_VER
 +#ifdef _DEBUG
 +      _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
 +#endif
  
 -      /* get wide char arguments and environment */
 -      si.newmode = 0;
 -      if (__wgetmainargs(&argc, &wargv, &wenv, _CRT_glob, &si) < 0)
 -              die_startup();
 +#ifdef USE_MSVC_CRTDBG
 +      _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
 +#endif
 +#endif
 +
 +      maybe_redirect_std_handles();
  
        /* determine size of argv and environ conversion buffer */
        maxlen = wcslen(wargv[0]);
        maxlen = 3 * maxlen + 1;
        buffer = malloc_startup(maxlen);
  
 -      /* convert command line arguments and environment to UTF-8 */
 +      /*
 +       * Create a UTF-8 version of w_argv. Also create a "save" copy
 +       * to remember all the string pointers because parse_options()
 +       * will remove claimed items from the argv that we pass down.
 +       */
 +      ALLOC_ARRAY(argv, argc + 1);
 +      ALLOC_ARRAY(save, argc + 1);
        for (i = 0; i < argc; i++)
 -              __argv[i] = wcstoutfdup_startup(buffer, wargv[i], maxlen);
 +              argv[i] = save[i] = wcstoutfdup_startup(buffer, wargv[i], maxlen);
 +      argv[i] = save[i] = NULL;
        free(buffer);
  
        /* fix Windows specific environment settings */
  
        /* initialize Unicode console */
        winansi_init();
 +
 +      /* invoke the real main() using our utf8 version of argv. */
 +      exit_status = main(argc, argv);
 +
 +      for (i = 0; i < argc; i++)
 +              free(save[i]);
 +      free(save);
 +      free(argv);
 +
 +      return exit_status;
  }
  
  int uname(struct utsname *buf)