diff options
author | Sven Strickroth <email@cs-ware.de> | 2019-06-28 17:05:57 +0200 |
---|---|---|
committer | Sven Strickroth <email@cs-ware.de> | 2019-07-01 14:01:16 +0200 |
commit | a692b52598d262884ce83944221d989f05e3f965 (patch) | |
tree | 996b1636def32066b227c0b808ed34229d744b9e | |
parent | bd616a79876029d77b51c989fa81b62b3b728a4a (diff) | |
download | libgit2-a692b52598d262884ce83944221d989f05e3f965.tar.gz |
Make Git for Windows root detection work with Git for Windows >= 2csware/findfiles_win32
Signed-off-by: Sven Strickroth <email@cs-ware.de>
-rw-r--r-- | src/win32/findfile.c | 61 |
1 files changed, 52 insertions, 9 deletions
diff --git a/src/win32/findfile.c b/src/win32/findfile.c index 6b3443aa0..d47ca2886 100644 --- a/src/win32/findfile.c +++ b/src/win32/findfile.c @@ -68,6 +68,42 @@ static wchar_t* win32_walkpath(wchar_t *path, wchar_t *buf, size_t buflen) return (path != base) ? path : NULL; } +static int win32_find_git_for_windows_architecture_root(_findfile_path *root_path, const wchar_t *subdir) +{ + /* Git for Windows >= 2 comes with a special architecture root (mingw64 and mingw32) + * under which "etc" and the "share" folders are located, check which we need (none is also ok) */ + + static const wchar_t *architecture_roots[3] = { + L"mingw64\\", + L"mingw32\\", + NULL, + }; + + const wchar_t **roots = architecture_roots; + DWORD subdir_len; + git_win32_path tmp_root; + for (; *roots != NULL; ++roots) { + if (wcscpy(tmp_root, root_path->path) && + root_path->len + wcslen(*roots) <= MAX_PATH && + wcscat(tmp_root, *roots) && + !_waccess(tmp_root, F_OK)) + { + wcscpy(root_path->path, tmp_root); + root_path->len += wcslen(*roots); + break; + } + } + + subdir_len = (DWORD)wcslen(subdir); + if (root_path->len + subdir_len >= MAX_PATH) + return -1; + + wcscat(root_path->path, subdir); + root_path->len += subdir_len; + + return 0; +} + static int win32_find_git_in_path(git_buf *buf, const wchar_t *gitexe, const wchar_t *subdir) { wchar_t *env = _wgetenv(L"PATH"), lastch; @@ -92,11 +128,13 @@ static int win32_find_git_in_path(git_buf *buf, const wchar_t *gitexe, const wch wcscpy(&root.path[root.len], gitexe); if (!_waccess(root.path, F_OK)) { - /* replace "bin\\" or "cmd\\" of a Git for Windows installation with subdir OR append path */ + /* check whether we found a Git for Windows installation and do some path adjustments OR just append subdir */ if (root.len > 5 && wcscmp(root.path - 4, L"cmd\\") || wcscmp(root.path - 4, L"bin\\")) { - if (root.len - 4 + wcslen(subdir) >= MAX_PATH) + /* strip "bin" or "cmd" and try to find architecture root for appending subdir */ + root.len -= 4; + root.path[root.len] = L'\0'; + if (win32_find_git_for_windows_architecture_root(&root, subdir)) continue; - wcscpy(&root.path[root.len - 4], subdir); } else { if (root.len + wcslen(subdir) >= MAX_PATH) continue; @@ -121,22 +159,21 @@ static int win32_find_git_in_registry( if (!RegOpenKeyExW(hive, key, 0, KEY_READ, &hKey)) { DWORD dwType, cbData; - git_win32_path path; + _findfile_path path; /* Ensure that the buffer is big enough to have the suffix attached * after we receive the result. */ cbData = (DWORD)(sizeof(path) - wcslen(subdir) * sizeof(wchar_t)); /* InstallLocation points to the root of the git directory */ - if (!RegQueryValueExW(hKey, L"InstallLocation", NULL, &dwType, (LPBYTE)path, &cbData) && + if (!RegQueryValueExW(hKey, L"InstallLocation", NULL, &dwType, (LPBYTE)path.path, &cbData) && dwType == REG_SZ) { - - /* Append the suffix */ - wcscat(path, subdir); + path.len = cbData; /* Convert to UTF-8, with forward slashes, and output the path * to the provided buffer */ - if (!win32_path_to_8(buf, path)) + if (!win32_find_git_for_windows_architecture_root(&path, subdir) && + !win32_path_to_8(buf, path.path)) error = 0; } @@ -189,6 +226,12 @@ int git_win32__find_system_dirs(git_buf *out, const wchar_t *subdir) &buf, HKEY_CURRENT_USER, REG_MSYSGIT_INSTALL_LOCAL, subdir) && buf.size) git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); +#ifdef WIN64 + if (!win32_find_git_in_registry( + &buf, HKEY_LOCAL_MACHINE, REG_MSYSGIT_INSTALL_LOCAL, subdir) && buf.size) + git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); +#endif + if (!win32_find_git_in_registry( &buf, HKEY_LOCAL_MACHINE, REG_MSYSGIT_INSTALL, subdir) && buf.size) git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); |