summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSven Strickroth <email@cs-ware.de>2019-06-28 17:05:57 +0200
committerSven Strickroth <email@cs-ware.de>2019-07-01 14:01:16 +0200
commita692b52598d262884ce83944221d989f05e3f965 (patch)
tree996b1636def32066b227c0b808ed34229d744b9e
parentbd616a79876029d77b51c989fa81b62b3b728a4a (diff)
downloadlibgit2-csware/findfiles_win32.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.c61
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);