diff options
-rw-r--r-- | src/sysdir.c | 20 | ||||
-rw-r--r-- | src/win32/findfile.c | 316 | ||||
-rw-r--r-- | src/win32/findfile.h | 6 | ||||
-rw-r--r-- | tests/win32/systemdir.c | 328 | ||||
-rw-r--r-- | tests/win32/systempath.c | 91 |
5 files changed, 490 insertions, 271 deletions
diff --git a/src/sysdir.c b/src/sysdir.c index c0e14f551..450cb509b 100644 --- a/src/sysdir.c +++ b/src/sysdir.c @@ -31,7 +31,7 @@ static int git_sysdir_guess_programdata_dirs(git_str *out) static int git_sysdir_guess_system_dirs(git_str *out) { #ifdef GIT_WIN32 - return git_win32__find_system_dirs(out, L"etc\\"); + return git_win32__find_system_dirs(out, "etc"); #else return git_str_sets(out, "/etc"); #endif @@ -154,7 +154,7 @@ static int git_sysdir_guess_xdg_dirs(git_str *out) static int git_sysdir_guess_template_dirs(git_str *out) { #ifdef GIT_WIN32 - return git_win32__find_system_dirs(out, L"share\\git-core\\templates"); + return git_win32__find_system_dirs(out, "share/git-core/templates"); #else return git_str_sets(out, "/usr/share/git-core/templates"); #endif @@ -190,22 +190,22 @@ int git_sysdir_global_init(void) error = git_sysdir__dirs[i].guess(&git_sysdir__dirs[i].buf); if (error) - return error; + return error; return git_runtime_shutdown_register(git_sysdir_global_shutdown); } int git_sysdir_reset(void) { - size_t i; - int error = 0; + size_t i; + int error = 0; - for (i = 0; !error && i < ARRAY_SIZE(git_sysdir__dirs); ++i) { - git_str_dispose(&git_sysdir__dirs[i].buf); - error = git_sysdir__dirs[i].guess(&git_sysdir__dirs[i].buf); - } + for (i = 0; !error && i < ARRAY_SIZE(git_sysdir__dirs); ++i) { + git_str_dispose(&git_sysdir__dirs[i].buf); + error = git_sysdir__dirs[i].guess(&git_sysdir__dirs[i].buf); + } - return error; + return error; } static int git_sysdir_check_selector(git_sysdir_t which) diff --git a/src/win32/findfile.c b/src/win32/findfile.c index b82347fc6..516391d7f 100644 --- a/src/win32/findfile.c +++ b/src/win32/findfile.c @@ -11,13 +11,8 @@ #include "utf-conv.h" #include "fs_path.h" -#define REG_MSYSGIT_INSTALL_LOCAL L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1" - -#ifndef _WIN64 -#define REG_MSYSGIT_INSTALL REG_MSYSGIT_INSTALL_LOCAL -#else -#define REG_MSYSGIT_INSTALL L"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1" -#endif +#define REG_GITFORWINDOWS_KEY L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1" +#define REG_GITFORWINDOWS_KEY_WOW64 L"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1" static int git_win32__expand_path(git_win32_path dest, const wchar_t *src) { @@ -44,164 +39,130 @@ static int win32_path_to_8(git_str *dest, const wchar_t *src) return git_str_sets(dest, utf8_path); } -static wchar_t *win32_walkpath(wchar_t *path, wchar_t *buf, size_t buflen) -{ - wchar_t term, *base = path; - - GIT_ASSERT_ARG_WITH_RETVAL(path, NULL); - GIT_ASSERT_ARG_WITH_RETVAL(buf, NULL); - GIT_ASSERT_ARG_WITH_RETVAL(buflen, NULL); - - term = (*path == L'"') ? *path++ : L';'; - - for (buflen--; *path && *path != term && buflen; buflen--) - *buf++ = *path++; - - *buf = L'\0'; /* reserved a byte via initial subtract */ +static git_win32_path mock_registry; +static bool mock_registry_set; - while (*path == term || *path == L';') - path++; - - return (path != base) ? path : NULL; -} - -static int win32_find_git_for_windows_architecture_root(git_win32_path root_path, const wchar_t *subdir) +extern int git_win32__set_registry_system_dir(const wchar_t *mock_sysdir) { - /* Git for Windows >= 2 comes with a special architecture root (mingw64 and mingw32) - * under which the "share" folder is located, check which we need (none is also ok) */ - - static const wchar_t *architecture_roots[4] = { - L"", // starting with Git 2.24 the etc folder is directly in the root folder - L"mingw64\\", - L"mingw32\\", - NULL, - }; - - const wchar_t **roots = architecture_roots; - size_t root_path_len = wcslen(root_path); - - for (; *roots != NULL; ++roots) { - git_win32_path tmp_root; - DWORD subdir_len; - if (wcscpy(tmp_root, root_path) && - root_path_len + wcslen(*roots) <= MAX_PATH && - wcscat(tmp_root, *roots) && - !_waccess(tmp_root, F_OK)) { - wcscpy(root_path, tmp_root); - root_path_len += (DWORD)wcslen(*roots); - - subdir_len = (DWORD)wcslen(subdir); - if (root_path_len + subdir_len >= MAX_PATH) - break; - - // append subdir and check whether it exists for the Git installation - wcscat(tmp_root, subdir); - if (!_waccess(tmp_root, F_OK)) { - wcscpy(root_path, tmp_root); - root_path_len += subdir_len; - break; - } + if (!mock_sysdir) { + mock_registry[0] = L'\0'; + mock_registry_set = false; + } else { + size_t len = wcslen(mock_sysdir); + + if (len > GIT_WIN_PATH_MAX) { + git_error_set(GIT_ERROR_INVALID, "mock path too long"); + return -1; } + + wcscpy(mock_registry, mock_sysdir); + mock_registry_set = true; } return 0; } -static int win32_find_git_in_path(git_str *buf, const wchar_t *gitexe, const wchar_t *subdir) +static int lookup_registry_key( + git_win32_path out, + const HKEY hive, + const wchar_t* key, + const wchar_t *value) { - wchar_t *path, *env, lastch; - git_win32_path root; - size_t gitexe_len = wcslen(gitexe); - DWORD len; - bool found = false; - - len = GetEnvironmentVariableW(L"PATH", NULL, 0); - - if (len < 0) - return -1; - - path = git__malloc(len * sizeof(wchar_t)); - GIT_ERROR_CHECK_ALLOC(path); + HKEY hkey; + DWORD type, size; + int error = GIT_ENOTFOUND; - len = GetEnvironmentVariableW(L"PATH", path, len); + /* + * Registry data may not be NUL terminated, provide room to do + * it ourselves. + */ + size = (DWORD)((sizeof(git_win32_path) - 1) * sizeof(wchar_t)); + + if (RegOpenKeyExW(hive, key, 0, KEY_READ, &hkey) != 0) + return GIT_ENOTFOUND; + + if (RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)out, &size) == 0 && + type == REG_SZ && + size > 0 && + size < sizeof(git_win32_path)) { + size_t wsize = size / sizeof(wchar_t); + size_t len = wsize - 1; + + if (out[wsize - 1] != L'\0') { + len = wsize; + out[wsize] = L'\0'; + } - if (len < 0) - return -1; + if (out[len - 1] == L'\\') + out[len - 1] = L'\0'; - env = path; + if (_waccess(out, F_OK) == 0) + error = 0; + } - while ((env = win32_walkpath(env, root, MAX_PATH-1)) && *root) { - size_t root_len = wcslen(root); - lastch = root[root_len - 1]; + RegCloseKey(hkey); + return error; +} - /* ensure trailing slash (MAX_PATH-1 to walkpath guarantees space) */ - if (lastch != L'/' && lastch != L'\\') { - root[root_len++] = L'\\'; - root[root_len] = L'\0'; - } +static int find_sysdir_in_registry(git_win32_path out) +{ + if (mock_registry_set) { + if (mock_registry[0] == L'\0') + return GIT_ENOTFOUND; - if (root_len + gitexe_len >= MAX_PATH) - continue; - - if (!_waccess(root, F_OK)) { - /* check whether we found a Git for Windows installation and do some path adjustments OR just append subdir */ - if ((root_len > 5 && wcscmp(root - 4, L"cmd\\")) || wcscmp(root - 4, L"bin\\")) { - /* strip "bin" or "cmd" and try to find architecture root for appending subdir */ - root_len -= 4; - root[root_len] = L'\0'; - if (win32_find_git_for_windows_architecture_root(root, subdir)) - continue; - } else { - if (root_len + wcslen(subdir) >= MAX_PATH) - continue; - wcscat(root, subdir); - } - - win32_path_to_8(buf, root); - found = true; - break; - } + wcscpy(out, mock_registry); + return 0; } - git__free(path); - return found ? 0 : GIT_ENOTFOUND; + if (lookup_registry_key(out, HKEY_CURRENT_USER, REG_GITFORWINDOWS_KEY, L"InstallLocation") == 0 || + lookup_registry_key(out, HKEY_CURRENT_USER, REG_GITFORWINDOWS_KEY_WOW64, L"InstallLocation") == 0 || + lookup_registry_key(out, HKEY_LOCAL_MACHINE, REG_GITFORWINDOWS_KEY, L"InstallLocation") == 0 || + lookup_registry_key(out, HKEY_LOCAL_MACHINE, REG_GITFORWINDOWS_KEY_WOW64, L"InstallLocation") == 0) + return 0; + + return GIT_ENOTFOUND; } -static int win32_find_git_in_registry( - git_str *buf, const HKEY hive, const wchar_t *key, const wchar_t *subdir) +static int find_sysdir_in_path(git_win32_path out) { - HKEY hKey; - int error = GIT_ENOTFOUND; + size_t out_len; - GIT_ASSERT_ARG(buf); + if (git_win32_path_find_executable(out, L"git.exe") < 0 && + git_win32_path_find_executable(out, L"git.cmd") < 0) + return GIT_ENOTFOUND; - if (!RegOpenKeyExW(hive, key, 0, KEY_READ, &hKey)) { - DWORD dwType, cbData; - git_win32_path path; + out_len = wcslen(out); - /* 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)); + /* Trim the file name */ + if (out_len <= CONST_STRLEN(L"git.exe")) + return GIT_ENOTFOUND; - /* InstallLocation points to the root of the git directory */ - if (!RegQueryValueExW(hKey, L"InstallLocation", NULL, &dwType, (LPBYTE)path, &cbData) && - dwType == REG_SZ) { + out_len -= CONST_STRLEN(L"git.exe"); - /* Convert to UTF-8, with forward slashes, and output the path - * to the provided buffer */ - if (!win32_find_git_for_windows_architecture_root(path, subdir) && - !win32_path_to_8(buf, path)) - error = 0; - } + if (out_len && out[out_len - 1] == L'\\') + out_len--; - RegCloseKey(hKey); - } + /* + * Git for Windows usually places the command in a 'bin' or + * 'cmd' directory, trim that. + */ + if (out_len >= CONST_STRLEN(L"\\bin") && + wcsncmp(&out[out_len - CONST_STRLEN(L"\\bin")], L"\\bin", CONST_STRLEN(L"\\bin")) == 0) + out_len -= CONST_STRLEN(L"\\bin"); + else if (out_len >= CONST_STRLEN(L"\\cmd") && + wcsncmp(&out[out_len - CONST_STRLEN(L"\\cmd")], L"\\cmd", CONST_STRLEN(L"\\cmd")) == 0) + out_len -= CONST_STRLEN(L"\\cmd"); - return error; + if (!out_len) + return GIT_ENOTFOUND; + + out[out_len] = L'\0'; + return 0; } static int win32_find_existing_dirs( - git_str *out, const wchar_t *tmpl[]) + git_str* out, + const wchar_t* tmpl[]) { git_win32_path path16; git_str buf = GIT_STR_INIT; @@ -210,9 +171,8 @@ static int win32_find_existing_dirs( for (; *tmpl != NULL; tmpl++) { if (!git_win32__expand_path(path16, *tmpl) && - path16[0] != L'%' && - !_waccess(path16, F_OK)) - { + path16[0] != L'%' && + !_waccess(path16, F_OK)) { win32_path_to_8(&buf, path16); if (buf.size) @@ -225,47 +185,67 @@ static int win32_find_existing_dirs( return (git_str_oom(out) ? -1 : 0); } -int git_win32__find_system_dir_in_path(git_str *out, const wchar_t *subdir) -{ - /* directories where git.exe & git.cmd are found */ - if (win32_find_git_in_path(out, L"git.exe", subdir) == 0) - return 0; - - return win32_find_git_in_path(out, L"git.cmd", subdir); -} - -static int git_win32__find_system_dir_in_registry(git_str *out, const wchar_t *subdir) +static int append_subdir(git_str *out, git_str *path, const char *subdir) { - git_str buf = GIT_STR_INIT; - - /* directories where git is installed according to registry */ - if (!win32_find_git_in_registry( - &buf, HKEY_CURRENT_USER, REG_MSYSGIT_INSTALL_LOCAL, subdir) && buf.size) - git_str_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); + static const char* architecture_roots[] = { + "", + "mingw64", + "mingw32", + NULL + }; + const char **root; + size_t orig_path_len = path->size; -#ifdef GIT_ARCH_64 - if (!win32_find_git_in_registry( - &buf, HKEY_LOCAL_MACHINE, REG_MSYSGIT_INSTALL_LOCAL, subdir) && buf.size) - git_str_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); -#endif + for (root = architecture_roots; *root; root++) { + if ((*root[0] && git_str_joinpath(path, path->ptr, *root) < 0) || + git_str_joinpath(path, path->ptr, subdir) < 0) + return -1; - if (!win32_find_git_in_registry( - &buf, HKEY_LOCAL_MACHINE, REG_MSYSGIT_INSTALL, subdir) && buf.size) - git_str_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); + if (git_fs_path_exists(path->ptr) && + git_str_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, path->ptr) < 0) + return -1; - git_str_dispose(&buf); + git_str_truncate(path, orig_path_len); + } - return (git_str_oom(out) ? -1 : 0); + return 0; } -int git_win32__find_system_dirs(git_str *out, const wchar_t *subdir) +int git_win32__find_system_dirs(git_str *out, const char *subdir) { + git_win32_path pathdir, regdir; + git_str path8 = GIT_STR_INIT; + bool has_pathdir, has_regdir; int error; - if ((error = git_win32__find_system_dir_in_path(out, subdir)) == 0) - error = git_win32__find_system_dir_in_registry(out, subdir); + has_pathdir = (find_sysdir_in_path(pathdir) == 0); + has_regdir = (find_sysdir_in_registry(regdir) == 0); - return error; + if (!has_pathdir && !has_regdir) + return GIT_ENOTFOUND; + + /* + * Usually the git in the path is the same git in the registry, + * in this case there's no need to duplicate the paths. + */ + if (has_pathdir && has_regdir && wcscmp(pathdir, regdir) == 0) + has_regdir = false; + + if (has_pathdir) { + if ((error = win32_path_to_8(&path8, pathdir)) < 0 || + (error = append_subdir(out, &path8, subdir)) < 0) + goto done; + } + + if (has_regdir) { + if ((error = win32_path_to_8(&path8, regdir)) < 0 || + (error = append_subdir(out, &path8, subdir)) < 0) + goto done; + } + +done: + git_str_dispose(&path8); + return error; } int git_win32__find_global_dirs(git_str *out) diff --git a/src/win32/findfile.h b/src/win32/findfile.h index 7f7691ce1..61fb7dbad 100644 --- a/src/win32/findfile.h +++ b/src/win32/findfile.h @@ -10,8 +10,10 @@ #include "common.h" -extern int git_win32__find_system_dir_in_path(git_str* out, const wchar_t* subdir); -extern int git_win32__find_system_dirs(git_str *out, const wchar_t *subpath); +/** Sets the mock registry root for Git for Windows for testing. */ +extern int git_win32__set_registry_system_dir(const wchar_t *mock_sysdir); + +extern int git_win32__find_system_dirs(git_str *out, const char *subpath); extern int git_win32__find_global_dirs(git_str *out); extern int git_win32__find_xdg_dirs(git_str *out); extern int git_win32__find_programdata_dirs(git_str *out); diff --git a/tests/win32/systemdir.c b/tests/win32/systemdir.c new file mode 100644 index 000000000..46fa06a50 --- /dev/null +++ b/tests/win32/systemdir.c @@ -0,0 +1,328 @@ +#include "clar_libgit2.h" +#include "futils.h" +#include "sysdir.h" +#include "win32/findfile.h" + +#ifdef GIT_WIN32 +static char *path_save; +static git_str gfw_path_root = GIT_STR_INIT; +static git_str gfw_registry_root = GIT_STR_INIT; +#endif + +void test_win32_systemdir__initialize(void) +{ +#ifdef GIT_WIN32 + git_str path_env = GIT_STR_INIT; + + path_save = cl_getenv("PATH"); + git_win32__set_registry_system_dir(L""); + + cl_git_pass(git_str_puts(&path_env, "C:\\GitTempTest\\Foo;\"c:\\program files\\doesnotexisttesttemp\";C:\\fakefakedoesnotexist")); + cl_setenv("PATH", path_env.ptr); + + cl_git_pass(git_str_puts(&gfw_path_root, clar_sandbox_path())); + cl_git_pass(git_str_puts(&gfw_path_root, "/fake_gfw_path_install")); + + cl_git_pass(git_str_puts(&gfw_registry_root, clar_sandbox_path())); + cl_git_pass(git_str_puts(&gfw_registry_root, "/fake_gfw_registry_install")); + + git_str_dispose(&path_env); +#endif +} + +void test_win32_systemdir__cleanup(void) +{ +#ifdef GIT_WIN32 + cl_fixture_cleanup("fake_gfw_path_install"); + cl_fixture_cleanup("fake_gfw_registry_install"); + git_str_dispose(&gfw_path_root); + git_str_dispose(&gfw_registry_root); + + cl_setenv("PATH", path_save); + git__free(path_save); + path_save = NULL; + + git_win32__set_registry_system_dir(NULL); + cl_sandbox_set_search_path_defaults(); +#endif +} + +#ifdef GIT_WIN32 +static void fix_path(git_str *s) +{ + char *c; + + for (c = s->ptr; *c; c++) { + if (*c == '/') + *c = '\\'; + } +} + +static void populate_fake_gfw( + git_str *expected_etc_dir, + const char *root, + const char *token, + bool create_gitconfig, + bool create_mingw64_gitconfig, + bool add_to_path, + bool add_to_registry) +{ + git_str bin_path = GIT_STR_INIT, exe_path = GIT_STR_INIT, + etc_path = GIT_STR_INIT, mingw64_path = GIT_STR_INIT, + config_path = GIT_STR_INIT, path_env = GIT_STR_INIT, + config_data = GIT_STR_INIT; + + cl_git_pass(git_str_puts(&bin_path, root)); + cl_git_pass(git_str_puts(&bin_path, "/cmd")); + cl_git_pass(git_futils_mkdir_r(bin_path.ptr, 0755)); + + cl_git_pass(git_str_puts(&exe_path, bin_path.ptr)); + cl_git_pass(git_str_puts(&exe_path, "/git.cmd")); + cl_git_mkfile(exe_path.ptr, "This is a fake executable."); + + cl_git_pass(git_str_puts(&etc_path, root)); + cl_git_pass(git_str_puts(&etc_path, "/etc")); + cl_git_pass(git_futils_mkdir_r(etc_path.ptr, 0755)); + + cl_git_pass(git_str_puts(&mingw64_path, root)); + cl_git_pass(git_str_puts(&mingw64_path, "/mingw64/etc")); + cl_git_pass(git_futils_mkdir_r(mingw64_path.ptr, 0755)); + + if (create_gitconfig) { + git_str_clear(&config_data); + git_str_printf(&config_data, "[gfw]\n\ttest = etc %s\n", token); + + cl_git_pass(git_str_puts(&config_path, etc_path.ptr)); + cl_git_pass(git_str_puts(&config_path, "/gitconfig")); + cl_git_mkfile(config_path.ptr, config_data.ptr); + } + + if (create_mingw64_gitconfig) { + git_str_clear(&config_data); + git_str_printf(&config_data, "[gfw]\n\ttest = mingw64 %s\n", token); + + git_str_clear(&config_path); + cl_git_pass(git_str_puts(&config_path, mingw64_path.ptr)); + cl_git_pass(git_str_puts(&config_path, "/gitconfig")); + cl_git_mkfile(config_path.ptr, config_data.ptr); + } + + if (add_to_path) { + fix_path(&bin_path); + cl_git_pass(git_str_puts(&path_env, "C:\\GitTempTest\\Foo;\"c:\\program files\\doesnotexisttesttemp\";")); + cl_git_pass(git_str_puts(&path_env, bin_path.ptr)); + cl_git_pass(git_str_puts(&path_env, ";C:\\fakefakedoesnotexist")); + cl_setenv("PATH", path_env.ptr); + } + + if (add_to_registry) { + git_win32_path registry_path; + size_t offset = 0; + + cl_assert(git_win32_path_from_utf8(registry_path, root) >= 0); + if (wcsncmp(registry_path, L"\\\\?\\", CONST_STRLEN("\\\\?\\")) == 0) + offset = CONST_STRLEN("\\\\?\\"); + git_win32__set_registry_system_dir(registry_path + offset); + } + + cl_git_pass(git_str_join(expected_etc_dir, GIT_PATH_LIST_SEPARATOR, expected_etc_dir->ptr, etc_path.ptr)); + cl_git_pass(git_str_join(expected_etc_dir, GIT_PATH_LIST_SEPARATOR, expected_etc_dir->ptr, mingw64_path.ptr)); + + git_str_dispose(&bin_path); + git_str_dispose(&exe_path); + git_str_dispose(&etc_path); + git_str_dispose(&mingw64_path); + git_str_dispose(&config_path); + git_str_dispose(&path_env); + git_str_dispose(&config_data); +} + +static void populate_fake_ecosystem( + git_str *expected_etc_dir, + bool create_gitconfig, + bool create_mingw64_gitconfig, + bool path, + bool registry) +{ + if (path) + populate_fake_gfw(expected_etc_dir, gfw_path_root.ptr, "path", create_gitconfig, create_mingw64_gitconfig, true, false); + + if (registry) + populate_fake_gfw(expected_etc_dir, gfw_registry_root.ptr, "registry", create_gitconfig, create_mingw64_gitconfig, false, true); +} +#endif + +void test_win32_systemdir__finds_etc_in_path(void) +{ +#ifdef GIT_WIN32 + git_str expected = GIT_STR_INIT, out = GIT_STR_INIT; + git_config *cfg; + git_buf value = GIT_BUF_INIT; + + populate_fake_ecosystem(&expected, true, false, true, false); + + cl_git_pass(git_win32__find_system_dirs(&out, "etc")); + cl_assert_equal_s(out.ptr, expected.ptr); + + git_sysdir_reset(); + + cl_git_pass(git_config_open_default(&cfg)); + cl_git_pass(git_config_get_string_buf(&value, cfg, "gfw.test")); + cl_assert_equal_s("etc path", value.ptr); + + git_buf_dispose(&value); + git_str_dispose(&expected); + git_str_dispose(&out); + git_config_free(cfg); +#endif +} + +void test_win32_systemdir__finds_mingw64_etc_in_path(void) +{ +#ifdef GIT_WIN32 + git_str expected = GIT_STR_INIT, out = GIT_STR_INIT; + git_config* cfg; + git_buf value = GIT_BUF_INIT; + + populate_fake_ecosystem(&expected, false, true, true, false); + + cl_git_pass(git_win32__find_system_dirs(&out, "etc")); + cl_assert_equal_s(out.ptr, expected.ptr); + + git_sysdir_reset(); + + cl_git_pass(git_config_open_default(&cfg)); + cl_git_pass(git_config_get_string_buf(&value, cfg, "gfw.test")); + cl_assert_equal_s("mingw64 path", value.ptr); + + git_buf_dispose(&value); + git_str_dispose(&expected); + git_str_dispose(&out); + git_config_free(cfg); +#endif +} + +void test_win32_systemdir__prefers_etc_to_mingw64_in_path(void) +{ +#ifdef GIT_WIN32 + git_str expected = GIT_STR_INIT, out = GIT_STR_INIT; + git_config* cfg; + git_buf value = GIT_BUF_INIT; + + populate_fake_ecosystem(&expected, true, true, true, false); + + cl_git_pass(git_win32__find_system_dirs(&out, "etc")); + cl_assert_equal_s(out.ptr, expected.ptr); + + git_sysdir_reset(); + + cl_git_pass(git_config_open_default(&cfg)); + cl_git_pass(git_config_get_string_buf(&value, cfg, "gfw.test")); + cl_assert_equal_s("etc path", value.ptr); + + git_buf_dispose(&value); + git_str_dispose(&expected); + git_str_dispose(&out); + git_config_free(cfg); +#endif +} + +void test_win32_systemdir__finds_etc_in_registry(void) +{ +#ifdef GIT_WIN32 + git_str expected = GIT_STR_INIT, out = GIT_STR_INIT; + git_config* cfg; + git_buf value = GIT_BUF_INIT; + + populate_fake_ecosystem(&expected, true, false, false, true); + + cl_git_pass(git_win32__find_system_dirs(&out, "etc")); + cl_assert_equal_s(out.ptr, expected.ptr); + + git_sysdir_reset(); + + cl_git_pass(git_config_open_default(&cfg)); + cl_git_pass(git_config_get_string_buf(&value, cfg, "gfw.test")); + cl_assert_equal_s("etc registry", value.ptr); + + git_buf_dispose(&value); + git_str_dispose(&expected); + git_str_dispose(&out); + git_config_free(cfg); +#endif +} + +void test_win32_systemdir__finds_mingw64_etc_in_registry(void) +{ +#ifdef GIT_WIN32 + git_str expected = GIT_STR_INIT, out = GIT_STR_INIT; + git_config* cfg; + git_buf value = GIT_BUF_INIT; + + populate_fake_ecosystem(&expected, false, true, false, true); + + cl_git_pass(git_win32__find_system_dirs(&out, "etc")); + cl_assert_equal_s(out.ptr, expected.ptr); + + git_sysdir_reset(); + + cl_git_pass(git_config_open_default(&cfg)); + cl_git_pass(git_config_get_string_buf(&value, cfg, "gfw.test")); + cl_assert_equal_s("mingw64 registry", value.ptr); + + git_buf_dispose(&value); + git_str_dispose(&expected); + git_str_dispose(&out); + git_config_free(cfg); +#endif +} + +void test_win32_systemdir__prefers_etc_to_mingw64_in_registry(void) +{ +#ifdef GIT_WIN32 + git_str expected = GIT_STR_INIT, out = GIT_STR_INIT; + git_config* cfg; + git_buf value = GIT_BUF_INIT; + + populate_fake_ecosystem(&expected, true, true, false, true); + + cl_git_pass(git_win32__find_system_dirs(&out, "etc")); + cl_assert_equal_s(out.ptr, expected.ptr); + + git_sysdir_reset(); + + cl_git_pass(git_config_open_default(&cfg)); + cl_git_pass(git_config_get_string_buf(&value, cfg, "gfw.test")); + cl_assert_equal_s("etc registry", value.ptr); + + git_buf_dispose(&value); + git_str_dispose(&expected); + git_str_dispose(&out); + git_config_free(cfg); +#endif +} + +void test_win32_systemdir__prefers_path_to_registry(void) +{ +#ifdef GIT_WIN32 + git_str expected = GIT_STR_INIT, out = GIT_STR_INIT; + git_config* cfg; + git_buf value = GIT_BUF_INIT; + + populate_fake_ecosystem(&expected, true, true, true, true); + + cl_git_pass(git_win32__find_system_dirs(&out, "etc")); + cl_assert_equal_s(out.ptr, expected.ptr); + + git_sysdir_reset(); + + cl_git_pass(git_config_open_default(&cfg)); + cl_git_pass(git_config_get_string_buf(&value, cfg, "gfw.test")); + cl_assert_equal_s("etc path", value.ptr); + + git_buf_dispose(&value); + git_str_dispose(&expected); + git_str_dispose(&out); + git_config_free(cfg); +#endif +} diff --git a/tests/win32/systempath.c b/tests/win32/systempath.c deleted file mode 100644 index 0b77f7703..000000000 --- a/tests/win32/systempath.c +++ /dev/null @@ -1,91 +0,0 @@ -#include "clar_libgit2.h" -#include "futils.h" -#include "sysdir.h" -#include "win32/findfile.h" - -static char *path_save; -static git_str gfw_root = GIT_STR_INIT; - -void test_win32_systempath__initialize(void) -{ - path_save = cl_getenv("PATH"); - - cl_git_pass(git_str_puts(&gfw_root, clar_sandbox_path())); - cl_git_pass(git_str_puts(&gfw_root, "/fake_gfw_install")); -} - -void test_win32_systempath__cleanup(void) -{ - cl_fixture_cleanup("fake_gfw_install"); - git_str_dispose(&gfw_root); - - cl_setenv("PATH", path_save); - git__free(path_save); - path_save = NULL; - - git_sysdir_reset(); -} - -static void fix_path(git_str *s) -{ - char *c; - - for (c = s->ptr; *c; c++) { - if (*c == '/') - *c = '\\'; - } -} - -void test_win32_systempath__etc_gitconfig(void) -{ - git_str bin_path = GIT_STR_INIT, exe_path = GIT_STR_INIT, - etc_path = GIT_STR_INIT, config_path = GIT_STR_INIT, - path_env = GIT_STR_INIT, out = GIT_STR_INIT; - git_config *cfg; - int value; - - cl_git_pass(git_str_puts(&bin_path, gfw_root.ptr)); - cl_git_pass(git_str_puts(&bin_path, "/cmd")); - cl_git_pass(git_futils_mkdir_r(bin_path.ptr, 0755)); - - cl_git_pass(git_str_puts(&exe_path, bin_path.ptr)); - cl_git_pass(git_str_puts(&exe_path, "/git.cmd")); - cl_git_mkfile(exe_path.ptr, "This is a fake executable."); - - cl_git_pass(git_str_puts(&etc_path, gfw_root.ptr)); - cl_git_pass(git_str_puts(&etc_path, "/etc")); - cl_git_pass(git_futils_mkdir_r(etc_path.ptr, 0755)); - - git_str_clear(&etc_path); - - cl_git_pass(git_str_puts(&etc_path, gfw_root.ptr)); - cl_git_pass(git_str_puts(&etc_path, "/etc")); - cl_git_pass(git_futils_mkdir_r(etc_path.ptr, 0755)); - - cl_git_pass(git_str_puts(&config_path, etc_path.ptr)); - cl_git_pass(git_str_puts(&config_path, "/gitconfig")); - cl_git_mkfile(config_path.ptr, "[gfw]\n\ttest = 1337\n"); - - fix_path(&bin_path); - - cl_git_pass(git_str_puts(&path_env, "C:\\GitTempTest\\Foo;\"c:\\program files\\doesnotexisttesttemp\";")); - cl_git_pass(git_str_puts(&path_env, bin_path.ptr)); - cl_git_pass(git_str_puts(&path_env, ";C:\\fakefakedoesnotexist")); - cl_setenv("PATH", path_env.ptr); - - cl_git_pass(git_win32__find_system_dir_in_path(&out, L"etc")); - cl_assert_equal_s(out.ptr, etc_path.ptr); - - git_sysdir_reset(); - - cl_git_pass(git_config_open_default(&cfg)); - cl_git_pass(git_config_get_int32(&value, cfg, "gfw.test")); - cl_assert_equal_i(1337, value); - - git_str_dispose(&exe_path); - git_str_dispose(&etc_path); - git_str_dispose(&config_path); - git_str_dispose(&path_env); - git_str_dispose(&out); - git_config_free(cfg); -} |