From c777afe8ca11ce90e9da6de405a9ec307890983b Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 8 Sep 2015 15:12:49 +0200 Subject: [PATCH 1/2] mingw: clean up the Git wrapper a bit We should not conflate the 'exepath' with the 'top-level directory'. The former should be the directory in which the executable lives while the latter should be the top-level directory ("POSIX root directory") as far as Git is concerned. Signed-off-by: Johannes Schindelin --- compat/win32/git-wrapper.c | 50 +++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/compat/win32/git-wrapper.c b/compat/win32/git-wrapper.c index 576d1af6b8bcb1..220f9ae4755023 100644 --- a/compat/win32/git-wrapper.c +++ b/compat/win32/git-wrapper.c @@ -37,7 +37,7 @@ static void print_error(LPCWSTR prefix, DWORD error_number) LocalFree((HLOCAL)buffer); } -static void setup_environment(LPWSTR exepath, int full_path) +static void setup_environment(LPWSTR top_level_path, int full_path) { WCHAR msystem[64]; LPWSTR path2 = NULL; @@ -90,7 +90,7 @@ static void setup_environment(LPWSTR exepath, int full_path) len = GetEnvironmentVariable(L"PATH", NULL, 0); len = sizeof(WCHAR) * (len + 2 * MAX_PATH); path2 = (LPWSTR)malloc(len); - wcscpy(path2, exepath); + wcscpy(path2, top_level_path); if (!full_path) PathAppend(path2, L"cmd;"); else { @@ -98,14 +98,14 @@ static void setup_environment(LPWSTR exepath, int full_path) if (_waccess(path2, 0) != -1) { /* We are in an MSys2-based setup */ wcscat(path2, L";"); - wcscat(path2, exepath); + wcscat(path2, top_level_path); PathAppend(path2, L"usr\\bin;"); } else { /* Fall back to MSys1 paths */ - wcscpy(path2, exepath); + wcscpy(path2, top_level_path); PathAppend(path2, L"bin;"); - wcscat(path2, exepath); + wcscat(path2, top_level_path); PathAppend(path2, L"mingw\\bin;"); } } @@ -386,7 +386,7 @@ int main(void) int r = 1, wait = 1, prefix_args_len = -1, needs_env_setup = 1, is_git_command = 1, full_path = 1, skip_arguments = 0, allocate_console = 0, show_console = 0; - WCHAR exepath[MAX_PATH], exe[MAX_PATH]; + WCHAR exepath[MAX_PATH], exe[MAX_PATH], top_level_path[MAX_PATH]; LPWSTR cmd = NULL, exep = exe, prefix_args = NULL, basename; LPWSTR working_directory = NULL; @@ -400,6 +400,7 @@ int main(void) fwprintf(stderr, L"Invalid executable path: %s\n", exepath); ExitProcess(1); } + wcscpy(top_level_path, exepath); basename = exepath + wcslen(exepath) + 1; if (configure_via_resource(basename, exepath, exep, &prefix_args, &prefix_args_len, @@ -412,25 +413,28 @@ int main(void) static WCHAR buffer[BUFSIZE]; wait = 0; allocate_console = 1; - if (!PathRemoveFileSpec(exepath)) { + if (!PathRemoveFileSpec(top_level_path)) { fwprintf(stderr, - L"Invalid executable path: %s\n", exepath); + L"Invalid executable path: %s\n", + top_level_path); ExitProcess(1); } /* set the default exe module */ - wcscpy(exe, exepath); + wcscpy(exe, top_level_path); PathAppend(exe, msystem_bin); PathAppend(exe, L"wish.exe"); if (_waccess(exe, 0) != -1) swprintf(buffer, BUFSIZE, L"\"%s\\%.*s\\libexec\\git-core\"", - exepath, wcslen(msystem_bin) - 4, msystem_bin); + top_level_path, + wcslen(msystem_bin) - 4, msystem_bin); else { - wcscpy(exe, exepath); + wcscpy(exe, top_level_path); PathAppend(exe, L"mingw\\bin\\wish.exe"); swprintf(buffer, BUFSIZE, - L"\"%s\\mingw\\libexec\\git-core\"", exepath); + L"\"%s\\mingw\\libexec\\git-core\"", + top_level_path); } PathAppend(buffer, L"git-gui"); prefix_args = buffer; @@ -450,39 +454,41 @@ int main(void) PathAppend(exe, L"git.exe"); } else if (!wcsicmp(basename, L"git.exe")) { - if (!PathRemoveFileSpec(exepath)) { + if (!PathRemoveFileSpec(top_level_path)) { fwprintf(stderr, - L"Invalid executable path: %s\n", exepath); + L"Invalid executable path: %s\n", + top_level_path); ExitProcess(1); } /* set the default exe module */ - wcscpy(exe, exepath); + wcscpy(exe, top_level_path); PathAppend(exe, msystem_bin); PathAppend(exe, L"git.exe"); if (_waccess(exe, 0) == -1) { - wcscpy(exe, exepath); + wcscpy(exe, top_level_path); PathAppend(exe, L"bin\\git.exe"); } } else if (!wcsicmp(basename, L"gitk.exe")) { static WCHAR buffer[BUFSIZE]; allocate_console = 1; - if (!PathRemoveFileSpec(exepath)) { + if (!PathRemoveFileSpec(top_level_path)) { fwprintf(stderr, - L"Invalid executable path: %s\n", exepath); + L"Invalid executable path: %s\n", + top_level_path); ExitProcess(1); } /* set the default exe module */ - wcscpy(exe, exepath); - swprintf(buffer, BUFSIZE, L"\"%s\"", exepath); + wcscpy(exe, top_level_path); + swprintf(buffer, BUFSIZE, L"\"%s\"", top_level_path); PathAppend(exe, msystem_bin); PathAppend(exe, L"wish.exe"); if (_waccess(exe, 0) != -1) PathAppend(buffer, msystem_bin); else { - wcscpy(exe, exepath); + wcscpy(exe, top_level_path); PathAppend(exe, L"mingw\\bin\\wish.exe"); PathAppend(buffer, L"mingw\\bin"); } @@ -492,7 +498,7 @@ int main(void) } if (needs_env_setup) - setup_environment(exepath, full_path); + setup_environment(top_level_path, full_path); cmd = fixup_commandline(exepath, &exep, &wait, prefix_args, prefix_args_len, is_git_command, skip_arguments); From 07e633bc974cb0d4eb9ffd6ef3f7e03c69ac3008 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Wed, 9 Sep 2015 14:10:27 +0200 Subject: [PATCH 2/2] mingw: let the Git wrapper determine the top-level directory The Git wrapper is also used as a redirector for Git for Windows' bin\bash.exe dropin: for backwards-compatibility, bin\bash.exe exists and simply sets up the environment variables before executing the *real* bash. However, due to our logic to use the directory in which the `.exe` lives as top-level directory (or one directory below for certain, known basenames such as `git.exe` and `gitk.exe`), the `PATH` environment variable was prefixed with the `/bin/bin` and `/bin/mingw/bin` directories -- which makes no sense. Instead, let's just auto-detect the top-level directory in the common case. Signed-off-by: Johannes Schindelin --- compat/win32/git-wrapper.c | 70 +++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/compat/win32/git-wrapper.c b/compat/win32/git-wrapper.c index 220f9ae4755023..2aef788a58b8f5 100644 --- a/compat/win32/git-wrapper.c +++ b/compat/win32/git-wrapper.c @@ -381,6 +381,46 @@ static int configure_via_resource(LPWSTR basename, LPWSTR exepath, LPWSTR exep, return 1; } +static void initialize_top_level_path(LPWSTR top_level_path, LPWSTR exepath, + LPWSTR msystem_bin, int strip_count) +{ + wcscpy(top_level_path, exepath); + + while (strip_count) { + if (strip_count < 0) { + int len = wcslen(top_level_path); + PathAppend(top_level_path, msystem_bin); + if (_waccess(top_level_path, 0) != -1) { + /* We are in an MSys2-based setup */ + top_level_path[len] = L'\0'; + return; + } + top_level_path[len] = L'\0'; + PathAppend(top_level_path, L"mingw\\bin"); + if (_waccess(top_level_path, 0) != -1) { + /* We are in an MSys-based setup */ + top_level_path[len] = L'\0'; + return; + } + top_level_path[len] = L'\0'; + if (!(++strip_count)) { + fwprintf(stderr, L"Top-level not found: %s\n", + exepath); + exit(1); + } + } + + if (!PathRemoveFileSpec(top_level_path)) { + fwprintf(stderr, L"Invalid executable path: %s\n", + exepath); + ExitProcess(1); + } + + if (strip_count > 0) + --strip_count; + } +} + int main(void) { int r = 1, wait = 1, prefix_args_len = -1, needs_env_setup = 1, @@ -393,6 +433,7 @@ int main(void) /* Determine MSys2-based Git path. */ swprintf(msystem_bin, sizeof(msystem_bin), L"mingw%d\\bin", (int) sizeof(void *) * 8); + *top_level_path = L'\0'; /* get the installation location */ GetModuleFileName(NULL, exepath, MAX_PATH); @@ -400,7 +441,6 @@ int main(void) fwprintf(stderr, L"Invalid executable path: %s\n", exepath); ExitProcess(1); } - wcscpy(top_level_path, exepath); basename = exepath + wcslen(exepath) + 1; if (configure_via_resource(basename, exepath, exep, &prefix_args, &prefix_args_len, @@ -413,12 +453,7 @@ int main(void) static WCHAR buffer[BUFSIZE]; wait = 0; allocate_console = 1; - if (!PathRemoveFileSpec(top_level_path)) { - fwprintf(stderr, - L"Invalid executable path: %s\n", - top_level_path); - ExitProcess(1); - } + initialize_top_level_path(top_level_path, exepath, NULL, 1); /* set the default exe module */ wcscpy(exe, top_level_path); @@ -454,12 +489,7 @@ int main(void) PathAppend(exe, L"git.exe"); } else if (!wcsicmp(basename, L"git.exe")) { - if (!PathRemoveFileSpec(top_level_path)) { - fwprintf(stderr, - L"Invalid executable path: %s\n", - top_level_path); - ExitProcess(1); - } + initialize_top_level_path(top_level_path, exepath, NULL, 1); /* set the default exe module */ wcscpy(exe, top_level_path); @@ -473,12 +503,7 @@ int main(void) else if (!wcsicmp(basename, L"gitk.exe")) { static WCHAR buffer[BUFSIZE]; allocate_console = 1; - if (!PathRemoveFileSpec(top_level_path)) { - fwprintf(stderr, - L"Invalid executable path: %s\n", - top_level_path); - ExitProcess(1); - } + initialize_top_level_path(top_level_path, exepath, NULL, 1); /* set the default exe module */ wcscpy(exe, top_level_path); @@ -497,8 +522,13 @@ int main(void) prefix_args_len = wcslen(buffer); } - if (needs_env_setup) + if (needs_env_setup) { + if (!top_level_path[0]) + initialize_top_level_path(top_level_path, exepath, + msystem_bin, -4); + setup_environment(top_level_path, full_path); + } cmd = fixup_commandline(exepath, &exep, &wait, prefix_args, prefix_args_len, is_git_command, skip_arguments);