summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2023-02-14 16:36:19 +0000
committerGitHub <noreply@github.com>2023-02-14 16:36:19 +0000
commitf7963f28cad7b2416a3cb0e55bc5adf85c82607b (patch)
treeec49ba5e08c74de903a9b99e712cf4e2192ec6bd
parent1119326aadfca4062679722b3ed975b569bcc0cf (diff)
parente0220e6a222b056ab44d68f41a62012077d2a3f3 (diff)
downloadlibgit2-f7963f28cad7b2416a3cb0e55bc5adf85c82607b.tar.gz
Merge pull request #6455 from libgit2/ethomson/sysdir
Support the notion of a home directory separately from global configuration directory
-rw-r--r--.github/workflows/main.yml14
-rwxr-xr-xci/build.sh20
-rwxr-xr-xci/setup-mingw-build.sh4
-rwxr-xr-xci/setup-win32-build.sh27
-rwxr-xr-xci/test.sh36
-rw-r--r--include/git2/common.h14
-rw-r--r--src/libgit2/attrcache.c2
-rw-r--r--src/libgit2/config.c2
-rw-r--r--src/libgit2/config_file.c4
-rw-r--r--src/libgit2/libgit2.c19
-rw-r--r--src/libgit2/sysdir.c301
-rw-r--r--src/libgit2/sysdir.h48
-rw-r--r--src/libgit2/transports/ssh.c105
-rw-r--r--src/util/futils.c3
-rw-r--r--src/util/win32/findfile.c286
-rw-r--r--src/util/win32/findfile.h22
-rw-r--r--tests/clar/clar_libgit2.c89
-rw-r--r--tests/clar/clar_libgit2.h21
-rw-r--r--tests/clar/main.c1
-rw-r--r--tests/libgit2/CMakeLists.txt2
-rw-r--r--tests/libgit2/config/include.c12
-rw-r--r--tests/libgit2/config/read.c9
-rw-r--r--tests/libgit2/ignore/path.c10
-rw-r--r--tests/libgit2/ignore/status.c8
-rw-r--r--tests/libgit2/online/clone.c163
-rw-r--r--tests/libgit2/remote/httpproxy.c4
-rw-r--r--tests/libgit2/win32/systemdir.c1
27 files changed, 772 insertions, 455 deletions
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 39cefdb19..f47469ca6 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -133,19 +133,25 @@ jobs:
- name: "Windows (amd64, Visual Studio)"
id: windows-amd64-vs
os: windows-2019
+ setup-script: win32
env:
ARCH: amd64
CMAKE_GENERATOR: Visual Studio 16 2019
- CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON
+ CMAKE_OPTIONS: -A x64 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_SSH=ON -DCMAKE_PREFIX_PATH=D:\Temp\libssh2
+ BUILD_PATH: C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin;D:\Temp\libssh2\bin
+ BUILD_TEMP: D:\Temp
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (x86, Visual Studio)"
id: windows-x86-vs
os: windows-2019
+ setup-script: win32
env:
ARCH: x86
CMAKE_GENERATOR: Visual Studio 16 2019
- CMAKE_OPTIONS: -A Win32 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_SHA1=HTTPS -DUSE_BUNDLED_ZLIB=ON
+ CMAKE_OPTIONS: -A Win32 -DWIN32_LEAKCHECK=ON -DDEPRECATE_HARD=ON -DUSE_SHA1=HTTPS -DUSE_BUNDLED_ZLIB=ON -DUSE_SSH=ON -DCMAKE_PREFIX_PATH=D:\Temp\libssh2
+ BUILD_PATH: C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files (x86)\CMake\bin;D:\Temp\libssh2\bin
+ BUILD_TEMP: D:\Temp
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (amd64, mingw)"
@@ -283,6 +289,10 @@ jobs:
- name: Build and test
run: |
export GITTEST_NEGOTIATE_PASSWORD="${{ secrets.GITTEST_NEGOTIATE_PASSWORD }}"
+ export GITTEST_GITHUB_SSH_KEY="${{ secrets.GITTEST_GITHUB_SSH_KEY }}"
+ export GITTEST_GITHUB_SSH_PUBKEY="${{ secrets.GITTEST_GITHUB_SSH_PUBKEY }}"
+ export GITTEST_GITHUB_SSH_PASSPHRASE="${{ secrets.GITTEST_GITHUB_SSH_PASSPHRASE }}"
+ export GITTEST_GITHUB_SSH_REMOTE_HOSTKEY="${{ secrets.GITTEST_GITHUB_SSH_REMOTE_HOSTKEY }}"
if [ -n "${{ matrix.platform.container.name }}" ]; then
mkdir build
diff --git a/ci/build.sh b/ci/build.sh
index 21a45af5f..80e7a61ae 100755
--- a/ci/build.sh
+++ b/ci/build.sh
@@ -13,16 +13,30 @@ BUILD_PATH=${BUILD_PATH:=$PATH}
CMAKE=$(which cmake)
CMAKE_GENERATOR=${CMAKE_GENERATOR:-Unix Makefiles}
+indent() { sed "s/^/ /"; }
+
+cygfullpath() {
+ result=$(echo "${1}" | tr \; \\n | while read -r element; do
+ if [ "${last}" != "" ]; then echo -n ":"; fi
+ echo -n $(cygpath "${element}")
+ last="${element}"
+ done)
+ if [ "${result}" = "" ]; then exit 1; fi
+ echo "${result}"
+}
+
if [[ "$(uname -s)" == MINGW* ]]; then
- BUILD_PATH=$(cygpath "$BUILD_PATH")
+ BUILD_PATH=$(cygfullpath "${BUILD_PATH}")
fi
-indent() { sed "s/^/ /"; }
echo "Source directory: ${SOURCE_DIR}"
echo "Build directory: ${BUILD_DIR}"
echo ""
+echo "Platform:"
+uname -s | indent
+
if [ "$(uname -s)" = "Darwin" ]; then
echo "macOS version:"
sw_vers | indent
@@ -40,7 +54,7 @@ echo "Kernel version:"
uname -a 2>&1 | indent
echo "CMake version:"
-env PATH="${BUILD_PATH}" "${CMAKE}" --version 2>&1 | indent
+env PATH="${BUILD_PATH}" "${CMAKE}" --version | head -1 2>&1 | indent
if test -n "${CC}"; then
echo "Compiler version:"
diff --git a/ci/setup-mingw-build.sh b/ci/setup-mingw-build.sh
index 3d72b24eb..6c444f584 100755
--- a/ci/setup-mingw-build.sh
+++ b/ci/setup-mingw-build.sh
@@ -11,9 +11,9 @@ BUILD_TEMP=$(cygpath $BUILD_TEMP)
case "$ARCH" in
amd64)
- MINGW_URI="https://github.com/libgit2/ci-dependencies/releases/download/2021-05-04/mingw-x86_64-8.1.0-release-win32-sjlj-rt_v6-rev0.zip";;
+ MINGW_URI="https://github.com/libgit2/ci-dependencies/releases/download/2023-01-23/mingw-x86_64-8.1.0-release-win32-sjlj-rt_v6-rev0.zip";;
x86)
- MINGW_URI="https://github.com/libgit2/ci-dependencies/releases/download/2021-05-04/mingw-i686-8.1.0-release-win32-sjlj-rt_v6-rev0.zip";;
+ MINGW_URI="https://github.com/libgit2/ci-dependencies/releases/download/2023-01-23/mingw-i686-8.1.0-release-win32-sjlj-rt_v6-rev0.zip";;
esac
if [ -z "$MINGW_URI" ]; then
diff --git a/ci/setup-win32-build.sh b/ci/setup-win32-build.sh
new file mode 100755
index 000000000..a8b81e5ef
--- /dev/null
+++ b/ci/setup-win32-build.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+set -ex
+
+echo "##############################################################################"
+echo "## Downloading libssh2"
+echo "##############################################################################"
+
+BUILD_TEMP=${BUILD_TEMP:=$TEMP}
+BUILD_TEMP=$(cygpath $BUILD_TEMP)
+
+case "$ARCH" in
+ amd64)
+ LIBSSH2_URI="https://github.com/libgit2/ci-dependencies/releases/download/2023-02-01/libssh2-20230201-amd64.zip";;
+ x86)
+ LIBSSH2_URI="https://github.com/libgit2/ci-dependencies/releases/download/2023-02-01-v2/libssh2-20230201-x86.zip";;
+esac
+
+if [ -z "$LIBSSH2_URI" ]; then
+ echo "No URL"
+ exit 1
+fi
+
+mkdir -p "$BUILD_TEMP"
+
+curl -s -L "$LIBSSH2_URI" -o "$BUILD_TEMP"/libssh2-"$ARCH".zip
+unzip -q "$BUILD_TEMP"/libssh2-"$ARCH".zip -d "$BUILD_TEMP"
diff --git a/ci/test.sh b/ci/test.sh
index 230daaaa0..e8bd22e03 100755
--- a/ci/test.sh
+++ b/ci/test.sh
@@ -13,9 +13,14 @@ fi
SOURCE_DIR=${SOURCE_DIR:-$( cd "$( dirname "${BASH_SOURCE[0]}" )" && dirname $( pwd ) )}
BUILD_DIR=$(pwd)
+BUILD_PATH=${BUILD_PATH:=$PATH}
+CTEST=$(which ctest)
TMPDIR=${TMPDIR:-/tmp}
USER=${USER:-$(whoami)}
+HOME=`mktemp -d ${TMPDIR}/home.XXXXXXXX`
+export CLAR_HOMEDIR=${HOME}
+
SUCCESS=1
CONTINUE_ON_FAILURE=0
@@ -72,7 +77,11 @@ run_test() {
RETURN_CODE=0
- CLAR_SUMMARY="${BUILD_DIR}/results_${1}.xml" ctest -V -R "^${1}$" || RETURN_CODE=$? && true
+ (
+ export PATH="${BUILD_PATH}"
+ export CLAR_SUMMARY="${BUILD_DIR}/results_${1}.xml"
+ "${CTEST}" -V -R "^${1}$"
+ ) || RETURN_CODE=$? && true
if [ "$RETURN_CODE" -eq 0 ]; then
FAILED=0
@@ -93,9 +102,31 @@ run_test() {
fi
}
+indent() { sed "s/^/ /"; }
+
+cygfullpath() {
+ result=$(echo "${1}" | tr \; \\n | while read -r element; do
+ if [ "${last}" != "" ]; then echo -n ":"; fi
+ echo -n $(cygpath "${element}")
+ last="${element}"
+ done)
+ if [ "${result}" = "" ]; then exit 1; fi
+ echo "${result}"
+}
+
+if [[ "$(uname -s)" == MINGW* ]]; then
+ BUILD_PATH=$(cygfullpath "$BUILD_PATH")
+fi
+
+
# Configure the test environment; run them early so that we're certain
# that they're started by the time we need them.
+echo "CTest version:"
+env PATH="${BUILD_PATH}" "${CTEST}" --version | head -1 2>&1 | indent
+
+echo ""
+
echo "##############################################################################"
echo "## Configuring test environment"
echo "##############################################################################"
@@ -140,7 +171,6 @@ fi
if [ -z "$SKIP_SSH_TESTS" ]; then
echo "Starting SSH server..."
- HOME=`mktemp -d ${TMPDIR}/home.XXXXXXXX`
SSHD_DIR=`mktemp -d ${TMPDIR}/sshd.XXXXXXXX`
git init --bare "${SSHD_DIR}/test.git" >/dev/null
cat >"${SSHD_DIR}/sshd_config" <<-EOF
@@ -384,7 +414,7 @@ if [ -z "$SKIP_FUZZERS" ]; then
echo "## Running fuzzers"
echo "##############################################################################"
- ctest -V -R 'fuzzer'
+ env PATH="${BUILD_PATH}" "${CTEST}" -V -R 'fuzzer'
fi
cleanup
diff --git a/include/git2/common.h b/include/git2/common.h
index ccf66334a..f968deb23 100644
--- a/include/git2/common.h
+++ b/include/git2/common.h
@@ -222,7 +222,9 @@ typedef enum {
GIT_OPT_GET_EXTENSIONS,
GIT_OPT_SET_EXTENSIONS,
GIT_OPT_GET_OWNER_VALIDATION,
- GIT_OPT_SET_OWNER_VALIDATION
+ GIT_OPT_SET_OWNER_VALIDATION,
+ GIT_OPT_GET_HOMEDIR,
+ GIT_OPT_SET_HOMEDIR
} git_libgit2_opt_t;
/**
@@ -468,6 +470,16 @@ typedef enum {
* > Set that repository directories should be owned by the current
* > user. The default is to validate ownership.
*
+ * opts(GIT_OPT_GET_HOMEDIR, git_buf *out)
+ * > Gets the current user's home directory, as it will be used
+ * > for file lookups. The path is written to the `out` buffer.
+ *
+ * opts(GIT_OPT_SET_HOMEDIR, const char *path)
+ * > Sets the directory used as the current user's home directory,
+ * > for file lookups.
+ * >
+ * > - `path` directory of home directory.
+ *
* @param option Option key
* @param ... value to set the option
* @return 0 on success, <0 on failure
diff --git a/src/libgit2/attrcache.c b/src/libgit2/attrcache.c
index b16d95c3c..405944ed1 100644
--- a/src/libgit2/attrcache.c
+++ b/src/libgit2/attrcache.c
@@ -300,7 +300,7 @@ static int attr_cache__lookup_path(
/* expand leading ~/ as needed */
if (cfgval && cfgval[0] == '~' && cfgval[1] == '/') {
- if (! (error = git_sysdir_expand_global_file(&buf, &cfgval[2])))
+ if (! (error = git_sysdir_expand_homedir_file(&buf, &cfgval[2])))
*out = git_str_detach(&buf);
} else if (cfgval) {
*out = git__strdup(cfgval);
diff --git a/src/libgit2/config.c b/src/libgit2/config.c
index 5c366e221..6d15a8db6 100644
--- a/src/libgit2/config.c
+++ b/src/libgit2/config.c
@@ -860,7 +860,7 @@ static int git_config__parse_path(git_str *out, const char *value)
return -1;
}
- return git_sysdir_expand_global_file(out, value[1] ? &value[2] : NULL);
+ return git_sysdir_expand_homedir_file(out, value[1] ? &value[2] : NULL);
}
return git_str_sets(out, value);
diff --git a/src/libgit2/config_file.c b/src/libgit2/config_file.c
index 66fcb8ae2..932ca7601 100644
--- a/src/libgit2/config_file.c
+++ b/src/libgit2/config_file.c
@@ -528,7 +528,7 @@ static int included_path(git_str *out, const char *dir, const char *path)
{
/* From the user's home */
if (path[0] == '~' && path[1] == '/')
- return git_sysdir_expand_global_file(out, &path[1]);
+ return git_sysdir_expand_homedir_file(out, &path[1]);
return git_fs_path_join_unrooted(out, path, dir, NULL);
}
@@ -616,7 +616,7 @@ static int do_match_gitdir(
git_fs_path_dirname_r(&pattern, cfg_file);
git_str_joinpath(&pattern, pattern.ptr, condition + 2);
} else if (condition[0] == '~' && git_fs_path_is_dirsep(condition[1]))
- git_sysdir_expand_global_file(&pattern, condition + 1);
+ git_sysdir_expand_homedir_file(&pattern, condition + 1);
else if (!git_fs_path_is_absolute(condition))
git_str_joinpath(&pattern, "**", condition);
else
diff --git a/src/libgit2/libgit2.c b/src/libgit2/libgit2.c
index 2fda0722e..f225122e5 100644
--- a/src/libgit2/libgit2.c
+++ b/src/libgit2/libgit2.c
@@ -414,6 +414,25 @@ int git_libgit2_opts(int key, ...)
git_repository__validate_ownership = (va_arg(ap, int) != 0);
break;
+ case GIT_OPT_GET_HOMEDIR:
+ {
+ git_buf *out = va_arg(ap, git_buf *);
+ git_str str = GIT_STR_INIT;
+ const git_str *tmp;
+
+ if ((error = git_buf_tostr(&str, out)) < 0 ||
+ (error = git_sysdir_get(&tmp, GIT_SYSDIR_HOME)) < 0 ||
+ (error = git_str_put(&str, tmp->ptr, tmp->size)) < 0)
+ break;
+
+ error = git_buf_fromstr(out, &str);
+ }
+ break;
+
+ case GIT_OPT_SET_HOMEDIR:
+ error = git_sysdir_set(GIT_SYSDIR_HOME, va_arg(ap, const char *));
+ break;
+
default:
git_error_set(GIT_ERROR_INVALID, "invalid option key");
error = -1;
diff --git a/src/libgit2/sysdir.c b/src/libgit2/sysdir.c
index 450cb509b..7838a6789 100644
--- a/src/libgit2/sysdir.c
+++ b/src/libgit2/sysdir.c
@@ -12,16 +12,262 @@
#include "fs_path.h"
#include <ctype.h>
#if GIT_WIN32
-#include "win32/findfile.h"
+# include "fs_path.h"
+# include "win32/path_w32.h"
+# include "win32/utf-conv.h"
#else
-#include <unistd.h>
-#include <pwd.h>
+# include <unistd.h>
+# include <pwd.h>
#endif
+#ifdef GIT_WIN32
+# 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 expand_win32_path(git_win32_path dest, const wchar_t *src)
+{
+ DWORD len = ExpandEnvironmentStringsW(src, dest, GIT_WIN_PATH_UTF16);
+
+ if (!len || len > GIT_WIN_PATH_UTF16)
+ return -1;
+
+ return 0;
+}
+
+static int win32_path_to_utf8(git_str *dest, const wchar_t *src)
+{
+ git_win32_utf8_path utf8_path;
+
+ if (git_win32_path_to_utf8(utf8_path, src) < 0) {
+ git_error_set(GIT_ERROR_OS, "unable to convert path to UTF-8");
+ return -1;
+ }
+
+ /* Convert backslashes to forward slashes */
+ git_fs_path_mkposix(utf8_path);
+
+ return git_str_sets(dest, utf8_path);
+}
+
+static git_win32_path mock_registry;
+static bool mock_registry_set;
+
+extern int git_win32__set_registry_system_dir(const wchar_t *mock_sysdir)
+{
+ 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 lookup_registry_key(
+ git_win32_path out,
+ const HKEY hive,
+ const wchar_t* key,
+ const wchar_t *value)
+{
+ HKEY hkey;
+ DWORD type, size;
+ int error = GIT_ENOTFOUND;
+
+ /*
+ * 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 (out[len - 1] == L'\\')
+ out[len - 1] = L'\0';
+
+ if (_waccess(out, F_OK) == 0)
+ error = 0;
+ }
+
+ RegCloseKey(hkey);
+ return error;
+}
+
+static int find_sysdir_in_registry(git_win32_path out)
+{
+ if (mock_registry_set) {
+ if (mock_registry[0] == L'\0')
+ return GIT_ENOTFOUND;
+
+ wcscpy(out, mock_registry);
+ return 0;
+ }
+
+ 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 find_sysdir_in_path(git_win32_path out)
+{
+ size_t out_len;
+
+ if (git_win32_path_find_executable(out, L"git.exe") < 0 &&
+ git_win32_path_find_executable(out, L"git.cmd") < 0)
+ return GIT_ENOTFOUND;
+
+ out_len = wcslen(out);
+
+ /* Trim the file name */
+ if (out_len <= CONST_STRLEN(L"git.exe"))
+ return GIT_ENOTFOUND;
+
+ out_len -= CONST_STRLEN(L"git.exe");
+
+ if (out_len && out[out_len - 1] == L'\\')
+ out_len--;
+
+ /*
+ * 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");
+
+ if (!out_len)
+ return GIT_ENOTFOUND;
+
+ out[out_len] = L'\0';
+ return 0;
+}
+
+static int find_win32_dirs(
+ git_str *out,
+ const wchar_t* tmpl[])
+{
+ git_win32_path path16;
+ git_str buf = GIT_STR_INIT;
+
+ git_str_clear(out);
+
+ for (; *tmpl != NULL; tmpl++) {
+ if (!expand_win32_path(path16, *tmpl) &&
+ path16[0] != L'%' &&
+ !_waccess(path16, F_OK)) {
+ win32_path_to_utf8(&buf, path16);
+
+ if (buf.size)
+ git_str_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr);
+ }
+ }
+
+ git_str_dispose(&buf);
+
+ return (git_str_oom(out) ? -1 : 0);
+}
+
+static int append_subdir(git_str *out, git_str *path, const char *subdir)
+{
+ static const char* architecture_roots[] = {
+ "",
+ "mingw64",
+ "mingw32",
+ NULL
+ };
+ const char **root;
+ size_t orig_path_len = path->size;
+
+ 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 (git_fs_path_exists(path->ptr) &&
+ git_str_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, path->ptr) < 0)
+ return -1;
+
+ git_str_truncate(path, orig_path_len);
+ }
+
+ return 0;
+}
+
+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;
+
+ has_pathdir = (find_sysdir_in_path(pathdir) == 0);
+ has_regdir = (find_sysdir_in_registry(regdir) == 0);
+
+ if (!has_pathdir && !has_regdir)
+ return 0;
+
+ /*
+ * 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_utf8(&path8, pathdir)) < 0 ||
+ (error = append_subdir(out, &path8, subdir)) < 0)
+ goto done;
+ }
+
+ if (has_regdir) {
+ if ((error = win32_path_to_utf8(&path8, regdir)) < 0 ||
+ (error = append_subdir(out, &path8, subdir)) < 0)
+ goto done;
+ }
+
+done:
+ git_str_dispose(&path8);
+ return error;
+}
+#endif /* WIN32 */
+
static int git_sysdir_guess_programdata_dirs(git_str *out)
{
#ifdef GIT_WIN32
- return git_win32__find_programdata_dirs(out);
+ static const wchar_t *programdata_tmpls[2] = {
+ L"%PROGRAMDATA%\\Git",
+ NULL,
+ };
+
+ return find_win32_dirs(out, programdata_tmpls);
#else
git_str_clear(out);
return 0;
@@ -75,10 +321,17 @@ out:
}
#endif
-static int git_sysdir_guess_global_dirs(git_str *out)
+static int git_sysdir_guess_home_dirs(git_str *out)
{
#ifdef GIT_WIN32
- return git_win32__find_global_dirs(out);
+ static const wchar_t *global_tmpls[4] = {
+ L"%HOME%\\",
+ L"%HOMEDRIVE%%HOMEPATH%\\",
+ L"%USERPROFILE%\\",
+ NULL,
+ };
+
+ return find_win32_dirs(out, global_tmpls);
#else
int error;
uid_t uid, euid;
@@ -114,10 +367,25 @@ static int git_sysdir_guess_global_dirs(git_str *out)
#endif
}
+static int git_sysdir_guess_global_dirs(git_str *out)
+{
+ return git_sysdir_guess_home_dirs(out);
+}
+
static int git_sysdir_guess_xdg_dirs(git_str *out)
{
#ifdef GIT_WIN32
- return git_win32__find_xdg_dirs(out);
+ static const wchar_t *global_tmpls[7] = {
+ L"%XDG_CONFIG_HOME%\\git",
+ L"%APPDATA%\\git",
+ L"%LOCALAPPDATA%\\git",
+ L"%HOME%\\.config\\git",
+ L"%HOMEDRIVE%%HOMEPATH%\\.config\\git",
+ L"%USERPROFILE%\\.config\\git",
+ NULL,
+ };
+
+ return find_win32_dirs(out, global_tmpls);
#else
git_str env = GIT_STR_INIT;
int error;
@@ -171,6 +439,7 @@ static struct git_sysdir__dir git_sysdir__dirs[] = {
{ GIT_STR_INIT, git_sysdir_guess_xdg_dirs },
{ GIT_STR_INIT, git_sysdir_guess_programdata_dirs },
{ GIT_STR_INIT, git_sysdir_guess_template_dirs },
+ { GIT_STR_INIT, git_sysdir_guess_home_dirs }
};
static void git_sysdir_global_shutdown(void)
@@ -350,6 +619,12 @@ int git_sysdir_find_template_dir(git_str *path)
path, NULL, GIT_SYSDIR_TEMPLATE, "template");
}
+int git_sysdir_find_homedir(git_str *path)
+{
+ return git_sysdir_find_in_dirlist(
+ path, NULL, GIT_SYSDIR_HOME, "home directory");
+}
+
int git_sysdir_expand_global_file(git_str *path, const char *filename)
{
int error;
@@ -361,3 +636,15 @@ int git_sysdir_expand_global_file(git_str *path, const char *filename)
return error;
}
+
+int git_sysdir_expand_homedir_file(git_str *path, const char *filename)
+{
+ int error;
+
+ if ((error = git_sysdir_find_homedir(path)) == 0) {
+ if (filename)
+ error = git_str_joinpath(path, path->ptr, filename);
+ }
+
+ return error;
+}
diff --git a/src/libgit2/sysdir.h b/src/libgit2/sysdir.h
index 568f27940..1d15bbf43 100644
--- a/src/libgit2/sysdir.h
+++ b/src/libgit2/sysdir.h
@@ -57,10 +57,22 @@ extern int git_sysdir_find_programdata_file(git_str *path, const char *filename)
extern int git_sysdir_find_template_dir(git_str *path);
/**
- * Expand the name of a "global" file (i.e. one in a user's home
- * directory). Unlike `find_global_file` (above), this makes no
- * attempt to check for the existence of the file, and is useful if
- * you want the full path regardless of existence.
+ * Find the home directory. On Windows, this will look at the `HOME`,
+ * `HOMEPATH`, and `USERPROFILE` environment variables (in that order)
+ * and return the first path that is set and exists. On other systems,
+ * this will simply return the contents of the `HOME` environment variable.
+ *
+ * @param path buffer to write the full path into
+ * @return 0 if found, GIT_ENOTFOUND if not found, or -1 on other OS error
+ */
+extern int git_sysdir_find_homedir(git_str *path);
+
+/**
+ * Expand the name of a "global" file -- by default inside the user's
+ * home directory, but can be overridden by the user configuration.
+ * Unlike `find_global_file` (above), this makes no attempt to check
+ * for the existence of the file, and is useful if you want the full
+ * path regardless of existence.
*
* @param path buffer to write the full path into
* @param filename name of file in the home directory
@@ -68,13 +80,25 @@ extern int git_sysdir_find_template_dir(git_str *path);
*/
extern int git_sysdir_expand_global_file(git_str *path, const char *filename);
+/**
+ * Expand the name of a file in the user's home directory. This
+ * function makes no attempt to check for the existence of the file,
+ * and is useful if you want the full path regardless of existence.
+ *
+ * @param path buffer to write the full path into
+ * @param filename name of file in the home directory
+ * @return 0 on success or -1 on error
+ */
+extern int git_sysdir_expand_homedir_file(git_str *path, const char *filename);
+
typedef enum {
- GIT_SYSDIR_SYSTEM = 0,
- GIT_SYSDIR_GLOBAL = 1,
- GIT_SYSDIR_XDG = 2,
+ GIT_SYSDIR_SYSTEM = 0,
+ GIT_SYSDIR_GLOBAL = 1,
+ GIT_SYSDIR_XDG = 2,
GIT_SYSDIR_PROGRAMDATA = 3,
- GIT_SYSDIR_TEMPLATE = 4,
- GIT_SYSDIR__MAX = 5
+ GIT_SYSDIR_TEMPLATE = 4,
+ GIT_SYSDIR_HOME = 5,
+ GIT_SYSDIR__MAX = 6
} git_sysdir_t;
/**
@@ -110,4 +134,10 @@ extern int git_sysdir_set(git_sysdir_t which, const char *paths);
*/
extern int git_sysdir_reset(void);
+/** Sets the registry system dir to a mock; for testing. */
+extern int git_win32__set_registry_system_dir(const wchar_t *mock_sysdir);
+
+/** Find the given system dir; for testing. */
+extern int git_win32__find_system_dirs(git_str *out, const char *subdir);
+
#endif
diff --git a/src/libgit2/transports/ssh.c b/src/libgit2/transports/ssh.c
index 85e779744..e90ab07e8 100644
--- a/src/libgit2/transports/ssh.c
+++ b/src/libgit2/transports/ssh.c
@@ -16,6 +16,7 @@
#include "netops.h"
#include "smart.h"
#include "streams/socket.h"
+#include "sysdir.h"
#include "git2/credential.h"
#include "git2/sys/credential.h"
@@ -421,7 +422,8 @@ static int request_creds(git_credential **out, ssh_subtransport *t, const char *
return 0;
}
-#define KNOWN_HOSTS_FILE ".ssh/known_hosts"
+#define SSH_DIR ".ssh"
+#define KNOWN_HOSTS_FILE "known_hosts"
/*
* Load the known_hosts file.
@@ -430,16 +432,14 @@ static int request_creds(git_credential **out, ssh_subtransport *t, const char *
*/
static int load_known_hosts(LIBSSH2_KNOWNHOSTS **hosts, LIBSSH2_SESSION *session)
{
- git_str path = GIT_STR_INIT, home = GIT_STR_INIT;
+ git_str path = GIT_STR_INIT, sshdir = GIT_STR_INIT;
LIBSSH2_KNOWNHOSTS *known_hosts = NULL;
int error;
GIT_ASSERT_ARG(hosts);
- if ((error = git__getenv(&home, "HOME")) < 0)
- return error;
-
- if ((error = git_str_joinpath(&path, git_str_cstr(&home), KNOWN_HOSTS_FILE)) < 0)
+ if ((error = git_sysdir_expand_homedir_file(&sshdir, SSH_DIR)) < 0 ||
+ (error = git_str_joinpath(&path, git_str_cstr(&sshdir), KNOWN_HOSTS_FILE)) < 0)
goto out;
if ((known_hosts = libssh2_knownhost_init(session)) == NULL) {
@@ -461,34 +461,32 @@ static int load_known_hosts(LIBSSH2_KNOWNHOSTS **hosts, LIBSSH2_SESSION *session
out:
*hosts = known_hosts;
- git_str_clear(&home);
- git_str_clear(&path);
+ git_str_dispose(&sshdir);
+ git_str_dispose(&path);
return error;
}
-static const char *hostkey_type_to_string(int type)
+static void add_hostkey_pref_if_avail(
+ LIBSSH2_KNOWNHOSTS *known_hosts,
+ const char *hostname,
+ int port,
+ git_str *prefs,
+ int type,
+ const char *type_name)
{
- switch (type) {
- case LIBSSH2_KNOWNHOST_KEY_SSHRSA:
- return "ssh-rsa";
- case LIBSSH2_KNOWNHOST_KEY_SSHDSS:
- return "ssh-dss";
-#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256
- case LIBSSH2_KNOWNHOST_KEY_ECDSA_256:
- return "ecdsa-sha2-nistp256";
- case LIBSSH2_KNOWNHOST_KEY_ECDSA_384:
- return "ecdsa-sha2-nistp384";
- case LIBSSH2_KNOWNHOST_KEY_ECDSA_521:
- return "ecdsa-sha2-nistp521";
-#endif
-#ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
- case LIBSSH2_KNOWNHOST_KEY_ED25519:
- return "ssh-ed25519";
-#endif
- }
+ struct libssh2_knownhost *host = NULL;
+ const char key = '\0';
+ int mask = LIBSSH2_KNOWNHOST_TYPE_PLAIN | LIBSSH2_KNOWNHOST_KEYENC_RAW | type;
+ int error;
- return NULL;
+ error = libssh2_knownhost_checkp(known_hosts, hostname, port, &key, 1, mask, &host);
+ if (error == LIBSSH2_KNOWNHOST_CHECK_MISMATCH) {
+ if (git_str_len(prefs) > 0) {
+ git_str_putc(prefs, ',');
+ }
+ git_str_puts(prefs, type_name);
+ }
}
/*
@@ -496,27 +494,27 @@ static const char *hostkey_type_to_string(int type)
* look it up with a nonsense key and using that mismatch to figure out what key
* we do have stored for the host.
*
- * Returns the string to pass to libssh2_session_method_pref or NULL if we were
- * unable to find anything or an error happened.
+ * Populates prefs with the string to pass to libssh2_session_method_pref.
*/
-static const char *find_hostkey_preference(LIBSSH2_KNOWNHOSTS *known_hosts, const char *hostname, int port)
+static void find_hostkey_preference(
+ LIBSSH2_KNOWNHOSTS *known_hosts,
+ const char *hostname,
+ int port,
+ git_str *prefs)
{
- struct libssh2_knownhost *host = NULL;
- /* Specify no key type so we don't filter on that */
- int type = LIBSSH2_KNOWNHOST_TYPE_PLAIN | LIBSSH2_KNOWNHOST_KEYENC_RAW;
- const char key = '\0';
- int error;
-
/*
- * In case of mismatch, we can find the type of key from known_hosts in
- * the returned host's information as it means that an entry was found
- * but our nonsense key obviously didn't match.
+ * The order here is important as it indicates the priority of what will
+ * be preferred.
*/
- error = libssh2_knownhost_checkp(known_hosts, hostname, port, &key, 1, type, &host);
- if (error == LIBSSH2_KNOWNHOST_CHECK_MISMATCH)
- return hostkey_type_to_string(host->typemask & LIBSSH2_KNOWNHOST_KEY_MASK);
-
- return NULL;
+#ifdef LIBSSH2_KNOWNHOST_KEY_ED25519
+ add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_ED25519, "ssh-ed25519");
+#endif
+#ifdef LIBSSH2_KNOWNHOST_KEY_ECDSA_256
+ add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_ECDSA_256, "ecdsa-sha2-nistp256");
+ add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_ECDSA_384, "ecdsa-sha2-nistp384");
+ add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_ECDSA_521, "ecdsa-sha2-nistp521");
+#endif
+ add_hostkey_pref_if_avail(known_hosts, hostname, port, prefs, LIBSSH2_KNOWNHOST_KEY_SSHRSA, "ssh-rsa");
}
static int _git_ssh_session_create(
@@ -526,11 +524,11 @@ static int _git_ssh_session_create(
int port,
git_stream *io)
{
- int rc = 0;
+ git_socket_stream *socket = GIT_CONTAINER_OF(io, git_socket_stream, parent);
LIBSSH2_SESSION *s;
LIBSSH2_KNOWNHOSTS *known_hosts;
- git_socket_stream *socket = GIT_CONTAINER_OF(io, git_socket_stream, parent);
- const char *keytype = NULL;
+ git_str prefs = GIT_STR_INIT;
+ int rc = 0;
GIT_ASSERT_ARG(session);
GIT_ASSERT_ARG(hosts);
@@ -547,16 +545,17 @@ static int _git_ssh_session_create(
return -1;
}
- if ((keytype = find_hostkey_preference(known_hosts, hostname, port)) != NULL) {
+ find_hostkey_preference(known_hosts, hostname, port, &prefs);
+ if (git_str_len(&prefs) > 0) {
do {
- rc = libssh2_session_method_pref(s, LIBSSH2_METHOD_HOSTKEY, keytype);
+ rc = libssh2_session_method_pref(s, LIBSSH2_METHOD_HOSTKEY, git_str_cstr(&prefs));
} while (LIBSSH2_ERROR_EAGAIN == rc || LIBSSH2_ERROR_TIMEOUT == rc);
if (rc != LIBSSH2_ERROR_NONE) {
ssh_error(s, "failed to set hostkey preference");
goto on_error;
}
}
-
+ git_str_dispose(&prefs);
do {
rc = libssh2_session_handshake(s, socket->s);
@@ -753,7 +752,7 @@ static int check_certificate(
if (error == GIT_PASSTHROUGH) {
error = git_error_state_restore(&previous_error);
} else if (error < 0 && !git_error_last()) {
- git_error_set(GIT_ERROR_NET, "user canceled hostkey check");
+ git_error_set(GIT_ERROR_NET, "unknown remote host key");
}
git_error_state_free(&previous_error);
@@ -1009,7 +1008,7 @@ static int list_auth_methods(int *out, LIBSSH2_SESSION *session, const char *use
/* either error, or the remote accepts NONE auth, which is bizarre, let's punt */
if (list == NULL && !libssh2_userauth_authenticated(session)) {
- ssh_error(session, "Failed to retrieve list of SSH authentication methods");
+ ssh_error(session, "remote rejected authentication");
return GIT_EAUTH;
}
diff --git a/src/util/futils.c b/src/util/futils.c
index cb872de09..084f1cd28 100644
--- a/src/util/futils.c
+++ b/src/util/futils.c
@@ -13,9 +13,6 @@
#include "rand.h"
#include <ctype.h>
-#if GIT_WIN32
-#include "win32/findfile.h"
-#endif
#define GIT_FILEMODE_DEFAULT 0100666
diff --git a/src/util/win32/findfile.c b/src/util/win32/findfile.c
deleted file mode 100644
index 725a90167..000000000
--- a/src/util/win32/findfile.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-
-#include "findfile.h"
-
-#include "path_w32.h"
-#include "utf-conv.h"
-#include "fs_path.h"
-
-#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)
-{
- DWORD len = ExpandEnvironmentStringsW(src, dest, GIT_WIN_PATH_UTF16);
-
- if (!len || len > GIT_WIN_PATH_UTF16)
- return -1;
-
- return 0;
-}
-
-static int win32_path_to_8(git_str *dest, const wchar_t *src)
-{
- git_win32_utf8_path utf8_path;
-
- if (git_win32_path_to_utf8(utf8_path, src) < 0) {
- git_error_set(GIT_ERROR_OS, "unable to convert path to UTF-8");
- return -1;
- }
-
- /* Convert backslashes to forward slashes */
- git_fs_path_mkposix(utf8_path);
-
- return git_str_sets(dest, utf8_path);
-}
-
-static git_win32_path mock_registry;
-static bool mock_registry_set;
-
-extern int git_win32__set_registry_system_dir(const wchar_t *mock_sysdir)
-{
- 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 lookup_registry_key(
- git_win32_path out,
- const HKEY hive,
- const wchar_t* key,
- const wchar_t *value)
-{
- HKEY hkey;
- DWORD type, size;
- int error = GIT_ENOTFOUND;
-
- /*
- * 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 (out[len - 1] == L'\\')
- out[len - 1] = L'\0';
-
- if (_waccess(out, F_OK) == 0)
- error = 0;
- }
-
- RegCloseKey(hkey);
- return error;
-}
-
-static int find_sysdir_in_registry(git_win32_path out)
-{
- if (mock_registry_set) {
- if (mock_registry[0] == L'\0')
- return GIT_ENOTFOUND;
-
- wcscpy(out, mock_registry);
- return 0;
- }
-
- 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 find_sysdir_in_path(git_win32_path out)
-{
- size_t out_len;
-
- if (git_win32_path_find_executable(out, L"git.exe") < 0 &&
- git_win32_path_find_executable(out, L"git.cmd") < 0)
- return GIT_ENOTFOUND;
-
- out_len = wcslen(out);
-
- /* Trim the file name */
- if (out_len <= CONST_STRLEN(L"git.exe"))
- return GIT_ENOTFOUND;
-
- out_len -= CONST_STRLEN(L"git.exe");
-
- if (out_len && out[out_len - 1] == L'\\')
- out_len--;
-
- /*
- * 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");
-
- 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_win32_path path16;
- git_str buf = GIT_STR_INIT;
-
- git_str_clear(out);
-
- for (; *tmpl != NULL; tmpl++) {
- if (!git_win32__expand_path(path16, *tmpl) &&
- path16[0] != L'%' &&
- !_waccess(path16, F_OK)) {
- win32_path_to_8(&buf, path16);
-
- if (buf.size)
- git_str_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr);
- }
- }
-
- git_str_dispose(&buf);
-
- return (git_str_oom(out) ? -1 : 0);
-}
-
-static int append_subdir(git_str *out, git_str *path, const char *subdir)
-{
- static const char* architecture_roots[] = {
- "",
- "mingw64",
- "mingw32",
- NULL
- };
- const char **root;
- size_t orig_path_len = path->size;
-
- 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 (git_fs_path_exists(path->ptr) &&
- git_str_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, path->ptr) < 0)
- return -1;
-
- git_str_truncate(path, orig_path_len);
- }
-
- return 0;
-}
-
-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;
-
- has_pathdir = (find_sysdir_in_path(pathdir) == 0);
- has_regdir = (find_sysdir_in_registry(regdir) == 0);
-
- if (!has_pathdir && !has_regdir)
- return 0;
-
- /*
- * 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)
-{
- static const wchar_t *global_tmpls[4] = {
- L"%HOME%\\",
- L"%HOMEDRIVE%%HOMEPATH%\\",
- L"%USERPROFILE%\\",
- NULL,
- };
-
- return win32_find_existing_dirs(out, global_tmpls);
-}
-
-int git_win32__find_xdg_dirs(git_str *out)
-{
- static const wchar_t *global_tmpls[7] = {
- L"%XDG_CONFIG_HOME%\\git",
- L"%APPDATA%\\git",
- L"%LOCALAPPDATA%\\git",
- L"%HOME%\\.config\\git",
- L"%HOMEDRIVE%%HOMEPATH%\\.config\\git",
- L"%USERPROFILE%\\.config\\git",
- NULL,
- };
-
- return win32_find_existing_dirs(out, global_tmpls);
-}
-
-int git_win32__find_programdata_dirs(git_str *out)
-{
- static const wchar_t *programdata_tmpls[2] = {
- L"%PROGRAMDATA%\\Git",
- NULL,
- };
-
- return win32_find_existing_dirs(out, programdata_tmpls);
-}
diff --git a/src/util/win32/findfile.h b/src/util/win32/findfile.h
deleted file mode 100644
index 7b191d1fe..000000000
--- a/src/util/win32/findfile.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) the libgit2 contributors. All rights reserved.
- *
- * This file is part of libgit2, distributed under the GNU GPL v2 with
- * a Linking Exception. For full terms see the included COPYING file.
- */
-
-#ifndef INCLUDE_win32_findfile_h__
-#define INCLUDE_win32_findfile_h__
-
-#include "git2_util.h"
-
-/** 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);
-
-#endif
-
diff --git a/tests/clar/clar_libgit2.c b/tests/clar/clar_libgit2.c
index 783b457f9..312e12103 100644
--- a/tests/clar/clar_libgit2.c
+++ b/tests/clar/clar_libgit2.c
@@ -1,6 +1,7 @@
#include "clar_libgit2.h"
#include "posix.h"
#include "fs_path.h"
+#include "futils.h"
#include "git2/sys/repository.h"
void cl_git_report_failure(
@@ -548,33 +549,95 @@ void clar__assert_equal_file(
(size_t)expected_bytes, (size_t)total_bytes);
}
-static git_buf _cl_restore_home = GIT_BUF_INIT;
+#define FAKE_HOMEDIR_NAME "cl_fake_home"
-void cl_fake_home_cleanup(void *payload)
+static git_buf _cl_restore_homedir = GIT_BUF_INIT;
+
+void cl_fake_homedir_cleanup(void *payload)
{
GIT_UNUSED(payload);
- if (_cl_restore_home.ptr) {
- cl_git_pass(git_libgit2_opts(
- GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, _cl_restore_home.ptr));
- git_buf_dispose(&_cl_restore_home);
+ if (_cl_restore_homedir.ptr) {
+ cl_git_pass(git_futils_rmdir_r(FAKE_HOMEDIR_NAME, NULL, GIT_RMDIR_REMOVE_FILES));
+
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_HOMEDIR, _cl_restore_homedir.ptr));
+ git_buf_dispose(&_cl_restore_homedir);
}
}
-void cl_fake_home(void)
+void cl_fake_homedir(git_str *out)
{
git_str path = GIT_STR_INIT;
cl_git_pass(git_libgit2_opts(
- GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, &_cl_restore_home));
+ GIT_OPT_GET_HOMEDIR, &_cl_restore_homedir));
+
+ cl_set_cleanup(cl_fake_homedir_cleanup, NULL);
+
+ /* TOC/TOU but merely attempts to prevent accidental cleanup. */
+ cl_assert(!git_fs_path_exists(FAKE_HOMEDIR_NAME));
+ cl_must_pass(p_mkdir(FAKE_HOMEDIR_NAME, 0777));
+ cl_git_pass(git_fs_path_prettify(&path, FAKE_HOMEDIR_NAME, NULL));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_HOMEDIR, path.ptr));
+
+ if (out)
+ git_str_swap(out, &path);
+
+ git_str_dispose(&path);
+}
+
+#define FAKE_GLOBALCONFIG_NAME "cl_fake_global"
+
+static git_buf _cl_restore_globalconfig = GIT_BUF_INIT;
+
+void cl_fake_globalconfig_cleanup(void *payload)
+{
+ GIT_UNUSED(payload);
+
+ if (_cl_restore_globalconfig.ptr) {
+ cl_git_pass(git_futils_rmdir_r(FAKE_GLOBALCONFIG_NAME, NULL, GIT_RMDIR_REMOVE_FILES));
+
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_HOMEDIR, _cl_restore_globalconfig.ptr));
+ git_buf_dispose(&_cl_restore_globalconfig);
+ }
+}
- cl_set_cleanup(cl_fake_home_cleanup, NULL);
+void cl_fake_globalconfig(git_str *out)
+{
+ git_str path = GIT_STR_INIT;
- if (!git_fs_path_exists("home"))
- cl_must_pass(p_mkdir("home", 0777));
- cl_git_pass(git_fs_path_prettify(&path, "home", NULL));
cl_git_pass(git_libgit2_opts(
- GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr));
+ GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, &_cl_restore_globalconfig));
+
+ cl_set_cleanup(cl_fake_globalconfig_cleanup, NULL);
+
+ /* TOC/TOU but merely attempts to prevent accidental cleanup. */
+ cl_assert(!git_fs_path_exists(FAKE_GLOBALCONFIG_NAME));
+ cl_must_pass(p_mkdir(FAKE_GLOBALCONFIG_NAME, 0777));
+ cl_git_pass(git_fs_path_prettify(&path, FAKE_GLOBALCONFIG_NAME, NULL));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr));
+
+ if (out)
+ git_str_swap(out, &path);
+
+ git_str_dispose(&path);
+}
+
+void cl_sandbox_set_homedir(const char *home)
+{
+ git_str path = GIT_STR_INIT;
+
+ if (home) {
+ git_libgit2_opts(GIT_OPT_SET_HOMEDIR, home);
+ } else {
+ git_str_joinpath(&path, clar_sandbox_path(), "__home");
+
+ if (!git_fs_path_exists(path.ptr))
+ cl_must_pass(p_mkdir(path.ptr, 0777));
+
+ git_libgit2_opts(GIT_OPT_SET_HOMEDIR, path.ptr);
+ }
+
git_str_dispose(&path);
}
diff --git a/tests/clar/clar_libgit2.h b/tests/clar/clar_libgit2.h
index d2d9da0aa..84405d21c 100644
--- a/tests/clar/clar_libgit2.h
+++ b/tests/clar/clar_libgit2.h
@@ -233,14 +233,23 @@ int cl_repo_get_bool(git_repository *repo, const char *cfg);
void cl_repo_set_string(git_repository *repo, const char *cfg, const char *value);
-/* set up a fake "home" directory and set libgit2 GLOBAL search path.
- *
- * automatically configures cleanup function to restore the regular search
- * path, although you can call it explicitly if you wish (with NULL).
+/*
+ * set up a fake "home" directory -- automatically configures cleanup
+ * function to restore the home directory, although you can call it
+ * explicitly if you wish (with NULL).
+ */
+void cl_fake_homedir(git_str *);
+void cl_fake_homedir_cleanup(void *);
+
+/*
+ * set up a fake global configuration directory -- automatically
+ * configures cleanup function to restore the global config
+ * although you can call it explicitly if you wish (with NULL).
*/
-void cl_fake_home(void);
-void cl_fake_home_cleanup(void *);
+void cl_fake_globalconfig(git_str *);
+void cl_fake_globalconfig_cleanup(void *);
+void cl_sandbox_set_homedir(const char *);
void cl_sandbox_set_search_path_defaults(void);
void cl_sandbox_disable_ownership_validation(void);
diff --git a/tests/clar/main.c b/tests/clar/main.c
index d879073a8..e3f4fe740 100644
--- a/tests/clar/main.c
+++ b/tests/clar/main.c
@@ -25,6 +25,7 @@ int main(int argc, char *argv[])
}
cl_global_trace_register();
+ cl_sandbox_set_homedir(getenv("CLAR_HOMEDIR"));
cl_sandbox_set_search_path_defaults();
cl_sandbox_disable_ownership_validation();
diff --git a/tests/libgit2/CMakeLists.txt b/tests/libgit2/CMakeLists.txt
index f581d3075..49691e1c1 100644
--- a/tests/libgit2/CMakeLists.txt
+++ b/tests/libgit2/CMakeLists.txt
@@ -66,7 +66,7 @@ endif()
include(AddClarTest)
add_clar_test(libgit2_tests offline -v -xonline)
add_clar_test(libgit2_tests invasive -v -sfilter::stream::bigfile -sodb::largefiles -siterator::workdir::filesystem_gunk -srepo::init -srepo::init::at_filesystem_root)
-add_clar_test(libgit2_tests online -v -sonline -xonline::customcert -xonline::clone::ssh_auth_methods)
+add_clar_test(libgit2_tests online -v -sonline -xonline::customcert)
add_clar_test(libgit2_tests online_customcert -v -sonline::customcert)
add_clar_test(libgit2_tests gitdaemon -v -sonline::push)
add_clar_test(libgit2_tests gitdaemon_namespace -v -sonline::clone::namespace)
diff --git a/tests/libgit2/config/include.c b/tests/libgit2/config/include.c
index 9328f3cf6..1b55fdc86 100644
--- a/tests/libgit2/config/include.c
+++ b/tests/libgit2/config/include.c
@@ -42,8 +42,13 @@ void test_config_include__absolute(void)
void test_config_include__homedir(void)
{
- cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, cl_fixture("config")));
+ git_str homefile = GIT_STR_INIT;
+
+ cl_fake_homedir(&homefile);
+ cl_git_pass(git_str_joinpath(&homefile, homefile.ptr, "config-included"));
+
cl_git_mkfile("config-include-homedir", "[include]\npath = ~/config-included");
+ cl_git_mkfile(homefile.ptr, "[foo \"bar\"]\n\tbaz = huzzah\n");
cl_git_pass(git_config_open_ondisk(&cfg, "config-include-homedir"));
@@ -53,6 +58,8 @@ void test_config_include__homedir(void)
cl_sandbox_set_search_path_defaults();
cl_git_pass(p_unlink("config-include-homedir"));
+
+ git_str_dispose(&homefile);
}
/* We need to pretend that the variables were defined where the file was included */
@@ -113,7 +120,8 @@ void test_config_include__missing(void)
void test_config_include__missing_homedir(void)
{
- cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, cl_fixture("config")));
+ cl_fake_homedir(NULL);
+
cl_git_mkfile("including", "[include]\npath = ~/.nonexistentfile\n[foo]\nbar = baz");
git_error_clear();
diff --git a/tests/libgit2/config/read.c b/tests/libgit2/config/read.c
index a2e668c20..ac6459b9e 100644
--- a/tests/libgit2/config/read.c
+++ b/tests/libgit2/config/read.c
@@ -728,14 +728,11 @@ void test_config_read__path(void)
{
git_config *cfg;
git_buf path = GIT_BUF_INIT;
- git_buf old_path = GIT_BUF_INIT;
git_str home_path = GIT_STR_INIT;
git_str expected_path = GIT_STR_INIT;
- cl_git_pass(p_mkdir("fakehome", 0777));
- cl_git_pass(git_fs_path_prettify(&home_path, "fakehome", NULL));
- cl_git_pass(git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, &old_path));
- cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, home_path.ptr));
+ cl_fake_homedir(&home_path);
+
cl_git_mkfile("./testconfig", "[some]\n path = ~/somefile");
cl_git_pass(git_fs_path_join_unrooted(&expected_path, "somefile", home_path.ptr, NULL));
@@ -761,8 +758,6 @@ void test_config_read__path(void)
cl_git_mkfile("./testconfig", "[some]\n path = ~user/foo");
cl_git_fail(git_config_get_path(&path, cfg, "some.path"));
- cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, old_path.ptr));
- git_buf_dispose(&old_path);
git_str_dispose(&home_path);
git_str_dispose(&expected_path);
git_config_free(cfg);
diff --git a/tests/libgit2/ignore/path.c b/tests/libgit2/ignore/path.c
index a574d1d79..17f28bc5d 100644
--- a/tests/libgit2/ignore/path.c
+++ b/tests/libgit2/ignore/path.c
@@ -286,14 +286,16 @@ void test_ignore_path__subdirectory_gitignore(void)
void test_ignore_path__expand_tilde_to_homedir(void)
{
+ git_str homefile = GIT_STR_INIT;
git_config *cfg;
assert_is_ignored(false, "example.global_with_tilde");
- cl_fake_home();
+ cl_fake_homedir(&homefile);
+ cl_git_pass(git_str_joinpath(&homefile, homefile.ptr, "globalexclude"));
/* construct fake home with fake global excludes */
- cl_git_mkfile("home/globalexclude", "# found me\n*.global_with_tilde\n");
+ cl_git_mkfile(homefile.ptr, "# found me\n*.global_with_tilde\n");
cl_git_pass(git_repository_config(&cfg, g_repo));
cl_git_pass(git_config_set_string(cfg, "core.excludesfile", "~/globalexclude"));
@@ -305,11 +307,13 @@ void test_ignore_path__expand_tilde_to_homedir(void)
cl_git_pass(git_futils_rmdir_r("home", NULL, GIT_RMDIR_REMOVE_FILES));
- cl_fake_home_cleanup(NULL);
+ cl_fake_homedir_cleanup(NULL);
git_attr_cache_flush(g_repo); /* must reset to pick up change */
assert_is_ignored(false, "example.global_with_tilde");
+
+ git_str_dispose(&homefile);
}
/* Ensure that the .gitignore in the subdirectory only affects
diff --git a/tests/libgit2/ignore/status.c b/tests/libgit2/ignore/status.c
index deb717590..a007774d7 100644
--- a/tests/libgit2/ignore/status.c
+++ b/tests/libgit2/ignore/status.c
@@ -363,6 +363,7 @@ void test_ignore_status__subdirectories_not_at_root(void)
void test_ignore_status__leading_slash_ignores(void)
{
+ git_str homedir = GIT_STR_INIT;
git_status_options opts = GIT_STATUS_OPTIONS_INIT;
status_entry_counts counts;
static const char *paths_2[] = {
@@ -385,8 +386,9 @@ void test_ignore_status__leading_slash_ignores(void)
make_test_data(test_repo_1, test_files_1);
- cl_fake_home();
- cl_git_mkfile("home/.gitignore", "/ignore_me\n");
+ cl_fake_homedir(&homedir);
+ cl_git_pass(git_str_joinpath(&homedir, homedir.ptr, ".gitignore"));
+ cl_git_mkfile(homedir.ptr, "/ignore_me\n");
{
git_config *cfg;
cl_git_pass(git_repository_config(&cfg, g_repo));
@@ -412,6 +414,8 @@ void test_ignore_status__leading_slash_ignores(void)
cl_assert_equal_i(counts.expected_entry_count, counts.entry_count);
cl_assert_equal_i(0, counts.wrong_status_flags_count);
cl_assert_equal_i(0, counts.wrong_sorted_path);
+
+ git_str_dispose(&homedir);
}
void test_ignore_status__multiple_leading_slash(void)
diff --git a/tests/libgit2/online/clone.c b/tests/libgit2/online/clone.c
index 96ff66ae0..ce469fa84 100644
--- a/tests/libgit2/online/clone.c
+++ b/tests/libgit2/online/clone.c
@@ -36,6 +36,11 @@ static char *_remote_expectcontinue = NULL;
static char *_remote_redirect_initial = NULL;
static char *_remote_redirect_subsequent = NULL;
+static char *_github_ssh_pubkey = NULL;
+static char *_github_ssh_privkey = NULL;
+static char *_github_ssh_passphrase = NULL;
+static char *_github_ssh_remotehostkey = NULL;
+
static int _orig_proxies_need_reset = 0;
static char *_orig_http_proxy = NULL;
static char *_orig_https_proxy = NULL;
@@ -85,6 +90,11 @@ void test_online_clone__initialize(void)
_remote_redirect_initial = cl_getenv("GITTEST_REMOTE_REDIRECT_INITIAL");
_remote_redirect_subsequent = cl_getenv("GITTEST_REMOTE_REDIRECT_SUBSEQUENT");
+ _github_ssh_pubkey = cl_getenv("GITTEST_GITHUB_SSH_PUBKEY");
+ _github_ssh_privkey = cl_getenv("GITTEST_GITHUB_SSH_KEY");
+ _github_ssh_passphrase = cl_getenv("GITTEST_GITHUB_SSH_PASSPHRASE");
+ _github_ssh_remotehostkey = cl_getenv("GITTEST_GITHUB_SSH_REMOTE_HOSTKEY");
+
if (_remote_expectcontinue)
git_libgit2_opts(GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE, 1);
@@ -119,6 +129,11 @@ void test_online_clone__cleanup(void)
git__free(_remote_redirect_initial);
git__free(_remote_redirect_subsequent);
+ git__free(_github_ssh_pubkey);
+ git__free(_github_ssh_privkey);
+ git__free(_github_ssh_passphrase);
+ git__free(_github_ssh_remotehostkey);
+
if (_orig_proxies_need_reset) {
cl_setenv("HTTP_PROXY", _orig_http_proxy);
cl_setenv("HTTPS_PROXY", _orig_https_proxy);
@@ -554,6 +569,68 @@ static int check_ssh_auth_methods(git_credential **cred, const char *url, const
return GIT_EUSER;
}
+static int succeed_certificate_check(git_cert *cert, int valid, const char *host, void *payload)
+{
+ GIT_UNUSED(cert);
+ GIT_UNUSED(valid);
+ GIT_UNUSED(payload);
+
+ cl_assert_equal_s("github.com", host);
+
+ return 0;
+}
+
+static int fail_certificate_check(git_cert *cert, int valid, const char *host, void *payload)
+{
+ GIT_UNUSED(cert);
+ GIT_UNUSED(valid);
+ GIT_UNUSED(host);
+ GIT_UNUSED(payload);
+
+ return GIT_ECERTIFICATE;
+}
+
+static int github_credentials(
+ git_credential **cred,
+ const char *url,
+ const char *username_from_url,
+ unsigned int allowed_types,
+ void *data)
+{
+ GIT_UNUSED(url);
+ GIT_UNUSED(username_from_url);
+ GIT_UNUSED(data);
+
+ if ((allowed_types & GIT_CREDENTIAL_USERNAME) != 0) {
+ return git_credential_username_new(cred, "git");
+ }
+
+ cl_assert((allowed_types & GIT_CREDENTIAL_SSH_KEY) != 0);
+
+ return git_credential_ssh_key_memory_new(cred,
+ "git",
+ _github_ssh_pubkey,
+ _github_ssh_privkey,
+ _github_ssh_passphrase);
+}
+
+void test_online_clone__ssh_github(void)
+{
+#if !defined(GIT_SSH) || !defined(GIT_SSH_MEMORY_CREDENTIALS)
+ clar__skip();
+#endif
+
+ if (!_github_ssh_pubkey || !_github_ssh_privkey)
+ clar__skip();
+
+ cl_fake_homedir(NULL);
+
+ g_options.fetch_opts.callbacks.credentials = github_credentials;
+ g_options.fetch_opts.callbacks.certificate_check = succeed_certificate_check;
+
+ cl_git_pass(git_clone(&g_repo, SSH_REPO_URL, "./foo", &g_options));
+}
+
void test_online_clone__ssh_auth_methods(void)
{
int with_user;
@@ -563,7 +640,7 @@ void test_online_clone__ssh_auth_methods(void)
#endif
g_options.fetch_opts.callbacks.credentials = check_ssh_auth_methods;
g_options.fetch_opts.callbacks.payload = &with_user;
- g_options.fetch_opts.callbacks.certificate_check = NULL;
+ g_options.fetch_opts.callbacks.certificate_check = succeed_certificate_check;
with_user = 0;
cl_git_fail_with(GIT_EUSER,
@@ -574,6 +651,69 @@ void test_online_clone__ssh_auth_methods(void)
git_clone(&g_repo, "ssh://git@github.com/libgit2/TestGitRepository", "./foo", &g_options));
}
+/*
+ * Ensure that the certificate check callback is still called, and
+ * can accept a host key that is not in the known hosts file.
+ */
+void test_online_clone__ssh_certcheck_accepts_unknown(void)
+{
+#if !defined(GIT_SSH) || !defined(GIT_SSH_MEMORY_CREDENTIALS)
+ clar__skip();
+#endif
+
+ if (!_github_ssh_pubkey || !_github_ssh_privkey)
+ clar__skip();
+
+ cl_fake_homedir(NULL);
+
+ g_options.fetch_opts.callbacks.credentials = github_credentials;
+
+ /* Ensure we fail without the certificate check */
+ cl_git_fail_with(GIT_ECERTIFICATE,
+ git_clone(&g_repo, SSH_REPO_URL, "./foo", NULL));
+
+ /* Set the callback to accept the certificate */
+ g_options.fetch_opts.callbacks.certificate_check = succeed_certificate_check;
+
+ cl_git_pass(git_clone(&g_repo, SSH_REPO_URL, "./foo", &g_options));
+}
+
+/*
+ * Ensure that the known hosts file is read and the certificate check
+ * callback is still called after that.
+ */
+void test_online_clone__ssh_certcheck_override_knownhosts(void)
+{
+ git_str knownhostsfile = GIT_STR_INIT;
+
+#if !defined(GIT_SSH) || !defined(GIT_SSH_MEMORY_CREDENTIALS)
+ clar__skip();
+#endif
+
+ if (!_github_ssh_pubkey || !_github_ssh_privkey || !_github_ssh_remotehostkey)
+ clar__skip();
+
+ g_options.fetch_opts.callbacks.credentials = github_credentials;
+
+ cl_fake_homedir(&knownhostsfile);
+ cl_git_pass(git_str_joinpath(&knownhostsfile, knownhostsfile.ptr, ".ssh"));
+ cl_git_pass(p_mkdir(knownhostsfile.ptr, 0777));
+
+ cl_git_pass(git_str_joinpath(&knownhostsfile, knownhostsfile.ptr, "known_hosts"));
+ cl_git_rewritefile(knownhostsfile.ptr, _github_ssh_remotehostkey);
+
+ /* Ensure we succeed without the certificate check */
+ cl_git_pass(git_clone(&g_repo, SSH_REPO_URL, "./foo", &g_options));
+ git_repository_free(g_repo);
+ g_repo = NULL;
+
+ /* Set the callback to reject the certificate */
+ g_options.fetch_opts.callbacks.certificate_check = fail_certificate_check;
+ cl_git_fail_with(GIT_ECERTIFICATE, git_clone(&g_repo, SSH_REPO_URL, "./bar", &g_options));
+
+ git_str_dispose(&knownhostsfile);
+}
+
static int custom_remote_ssh_with_paths(
git_remote **out,
git_repository *repo,
@@ -746,16 +886,6 @@ void test_online_clone__ssh_memory_auth(void)
cl_git_pass(git_clone(&g_repo, _remote_url, "./foo", &g_options));
}
-static int fail_certificate_check(git_cert *cert, int valid, const char *host, void *payload)
-{
- GIT_UNUSED(cert);
- GIT_UNUSED(valid);
- GIT_UNUSED(host);
- GIT_UNUSED(payload);
-
- return GIT_ECERTIFICATE;
-}
-
void test_online_clone__certificate_invalid(void)
{
g_options.fetch_opts.callbacks.certificate_check = fail_certificate_check;
@@ -769,17 +899,6 @@ void test_online_clone__certificate_invalid(void)
#endif
}
-static int succeed_certificate_check(git_cert *cert, int valid, const char *host, void *payload)
-{
- GIT_UNUSED(cert);
- GIT_UNUSED(valid);
- GIT_UNUSED(payload);
-
- cl_assert_equal_s("github.com", host);
-
- return 0;
-}
-
void test_online_clone__certificate_valid(void)
{
g_options.fetch_opts.callbacks.certificate_check = succeed_certificate_check;
diff --git a/tests/libgit2/remote/httpproxy.c b/tests/libgit2/remote/httpproxy.c
index f62a2545b..6ba00b7c9 100644
--- a/tests/libgit2/remote/httpproxy.c
+++ b/tests/libgit2/remote/httpproxy.c
@@ -132,7 +132,7 @@ static void assert_global_config_match(const char *config, const char *expected)
void test_remote_httpproxy__config_overrides_detached_remote(void)
{
- cl_fake_home();
+ cl_fake_globalconfig(NULL);
assert_global_config_match(NULL, NULL);
assert_global_config_match("http.proxy", "http://localhost:1/");
@@ -141,8 +141,6 @@ void test_remote_httpproxy__config_overrides_detached_remote(void)
assert_global_config_match("http.https://github.com/libgit2.proxy", "http://localhost:4/");
assert_global_config_match("http.https://github.com/libgit2/.proxy", "http://localhost:5/");
assert_global_config_match("http.https://github.com/libgit2/libgit2.proxy", "http://localhost:6/");
-
- cl_git_pass(git_futils_rmdir_r("home", NULL, GIT_RMDIR_REMOVE_FILES));
}
void test_remote_httpproxy__env(void)
diff --git a/tests/libgit2/win32/systemdir.c b/tests/libgit2/win32/systemdir.c
index 52c1784a1..9039f05b2 100644
--- a/tests/libgit2/win32/systemdir.c
+++ b/tests/libgit2/win32/systemdir.c
@@ -1,7 +1,6 @@
#include "clar_libgit2.h"
#include "futils.h"
#include "sysdir.h"
-#include "win32/findfile.h"
#ifdef GIT_WIN32
static char *path_save;