summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xtests/benchmarks/benchmark.sh10
-rw-r--r--tests/clar/clar.c5
-rw-r--r--tests/clar/clar/fixtures.h2
-rw-r--r--tests/clar/clar/fs.h2
-rw-r--r--tests/clar/clar/sandbox.h45
-rw-r--r--tests/clar/clar_libgit2.h17
-rw-r--r--tests/libgit2/attr/repo.c25
-rw-r--r--tests/libgit2/blame/buffer.c236
-rw-r--r--tests/libgit2/checkout/tree.c2
-rw-r--r--tests/libgit2/cherrypick/workdir.c2
-rw-r--r--tests/libgit2/clone/local.c10
-rw-r--r--tests/libgit2/commit/commit.c4
-rw-r--r--tests/libgit2/commit/create.c112
-rw-r--r--tests/libgit2/commit/signature.c9
-rw-r--r--tests/libgit2/commit/write.c2
-rw-r--r--tests/libgit2/config/configlevel.c41
-rw-r--r--tests/libgit2/config/include.c4
-rw-r--r--tests/libgit2/config/memory.c75
-rw-r--r--tests/libgit2/config/multivar.c31
-rw-r--r--tests/libgit2/config/read.c2
-rw-r--r--tests/libgit2/config/readonly.c2
-rw-r--r--tests/libgit2/config/snapshot.c43
-rw-r--r--tests/libgit2/config/write.c30
-rw-r--r--tests/libgit2/core/opts.c12
-rw-r--r--tests/libgit2/core/useragent.c53
-rw-r--r--tests/libgit2/diff/parse.c25
-rw-r--r--tests/libgit2/diff/rename.c48
-rw-r--r--tests/libgit2/diff/workdir.c57
-rw-r--r--tests/libgit2/grafts/shallow.c2
-rw-r--r--tests/libgit2/iterator/workdir.c6
-rw-r--r--tests/libgit2/merge/trees/renames.c19
-rw-r--r--tests/libgit2/message/trailer.c31
-rw-r--r--tests/libgit2/network/remote/local.c4
-rw-r--r--tests/libgit2/network/remote/rename.c2
-rw-r--r--tests/libgit2/odb/backend/nobackend.c4
-rw-r--r--tests/libgit2/odb/freshen.c2
-rw-r--r--tests/libgit2/odb/sorting.c7
-rw-r--r--tests/libgit2/online/clone.c52
-rw-r--r--tests/libgit2/online/fetch.c65
-rw-r--r--tests/libgit2/online/push.c221
-rw-r--r--tests/libgit2/online/shallow.c99
-rw-r--r--tests/libgit2/pack/packbuilder.c70
-rw-r--r--tests/libgit2/rebase/sign.c6
-rw-r--r--tests/libgit2/refs/branches/delete.c15
-rw-r--r--tests/libgit2/refs/reflog/messages.c2
-rw-r--r--tests/libgit2/refs/revparse.c19
-rw-r--r--tests/libgit2/remote/fetch.c5
-rw-r--r--tests/libgit2/repo/getters.c60
-rw-r--r--tests/libgit2/repo/init.c25
-rw-r--r--tests/libgit2/repo/new.c35
-rw-r--r--tests/libgit2/repo/open.c232
-rw-r--r--tests/libgit2/repo/shallow.c2
-rw-r--r--tests/libgit2/revert/workdir.c6
-rw-r--r--tests/libgit2/revwalk/basic.c3
-rw-r--r--tests/libgit2/status/worktree.c10
-rw-r--r--tests/libgit2/submodule/lookup.c18
-rw-r--r--tests/libgit2/trace/trace.c24
-rw-r--r--tests/libgit2/transport/ssh_exec.c79
-rw-r--r--tests/libgit2/worktree/config.c81
-rw-r--r--tests/libgit2/worktree/refs.c62
-rw-r--r--tests/libgit2/worktree/worktree.c57
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/29bin0 -> 75 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/54/c9d15687fb4f56e08252662962d6d1dbc09d9d3
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/57/16ca5987cbf97d6bb54920bea6adde242d87e6bin0 -> 19 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/60/b12be2d2f57977ce83d8dfd32e2394ac1ba1a2bin0 -> 38 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/a6/5140d5ec9f47064f614ecf8e43776baa5c0c11bin0 -> 75 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/ab/347abd8cda4a0e3b8bb42bb620c0c72c7df779bin0 -> 165 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/bc/114411903fd2afaa4bb9b85ed13f27e37ac375bin0 -> 74 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/cd/edf9760406dc79e0c6a8899ce9f180ec2a23a02
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/de/06afe070b65f94d7d791c39a6d389c58dda60dbin0 -> 75 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/e5/0a49f9558d09d4d3bfc108363bb24c127ed263bin0 -> 20 bytes
-rw-r--r--tests/resources/merge-resolve/.gitted/objects/ea/789495e0a72efadcd0f86a48f4c9ed435bb8a33
-rw-r--r--tests/resources/merge-resolve/.gitted/refs/heads/emptyfile_renames1
-rw-r--r--tests/resources/merge-resolve/.gitted/refs/heads/emptyfile_renames-branch1
-rw-r--r--tests/resources/process/cat.bat2
-rw-r--r--tests/resources/process/env.cmd2
-rwxr-xr-xtests/resources/process/helloworld.sh3
-rw-r--r--tests/resources/process/pwd.bat2
-rw-r--r--tests/resources/push.sh2
-rw-r--r--tests/resources/pushoptions.git/HEAD1
-rw-r--r--tests/resources/pushoptions.git/branches/.gitignore0
-rw-r--r--tests/resources/pushoptions.git/config8
-rw-r--r--tests/resources/pushoptions.git/description1
-rwxr-xr-xtests/resources/pushoptions.git/hooks/pre-receive3
-rw-r--r--tests/resources/pushoptions.git/info/exclude6
-rw-r--r--tests/resources/pushoptions.git/objects/info/.gitignore0
-rw-r--r--tests/resources/pushoptions.git/objects/pack/.gitignore0
-rw-r--r--tests/resources/pushoptions.git/refs/heads/.gitignore0
-rw-r--r--tests/resources/pushoptions.git/refs/tags/.gitignore0
-rw-r--r--tests/resources/status_skiphash/.gitted/COMMIT_EDITMSG1
-rw-r--r--tests/resources/status_skiphash/.gitted/HEAD1
-rw-r--r--tests/resources/status_skiphash/.gitted/MERGE_RR0
-rw-r--r--tests/resources/status_skiphash/.gitted/config9
-rw-r--r--tests/resources/status_skiphash/.gitted/description1
-rw-r--r--tests/resources/status_skiphash/.gitted/indexbin0 -> 137 bytes
-rw-r--r--tests/resources/status_skiphash/.gitted/info/exclude6
-rw-r--r--tests/resources/status_skiphash/.gitted/logs/HEAD1
-rw-r--r--tests/resources/status_skiphash/.gitted/logs/refs/heads/main1
-rw-r--r--tests/resources/status_skiphash/.gitted/objects/34/f4c90b237fcb4c677772a6093f3cba239c41a5bin0 -> 510 bytes
-rw-r--r--tests/resources/status_skiphash/.gitted/objects/71/a21e67674e9717aa7380e5782ec5e070a8d7e0bin0 -> 53 bytes
-rw-r--r--tests/resources/status_skiphash/.gitted/objects/d7/c1f165e51adbbfd7760162b7a5802d4117740cbin0 -> 26 bytes
-rw-r--r--tests/resources/status_skiphash/.gitted/refs/heads/main1
-rw-r--r--tests/resources/status_skiphash/new_file1
-rw-r--r--tests/resources/testrepo/.gitted/config2
-rw-r--r--tests/resources/testrepo/.gitted/config.worktree2
-rw-r--r--tests/resources/testrepo/.gitted/worktrees/testrepo-worktree/config.worktree2
-rw-r--r--tests/util/assert.c3
-rw-r--r--tests/util/errors.c84
-rw-r--r--tests/util/path.c768
-rw-r--r--tests/util/path/core.c804
-rw-r--r--tests/util/path/win32.c33
-rw-r--r--tests/util/process/env.c111
-rw-r--r--tests/util/process/start.c247
-rw-r--r--tests/util/process/win32.c63
-rw-r--r--tests/util/string.c6
115 files changed, 3354 insertions, 1064 deletions
diff --git a/tests/benchmarks/benchmark.sh b/tests/benchmarks/benchmark.sh
index 4a89807..4cb2b2f 100755
--- a/tests/benchmarks/benchmark.sh
+++ b/tests/benchmarks/benchmark.sh
@@ -6,9 +6,10 @@ set -eo pipefail
# parse the command line
#
-usage() { echo "usage: $(basename "$0") [--cli <path>] [--baseline-cli <path>] [--suite <suite>] [--json <path>] [--zip <path>] [--verbose] [--debug]"; }
+usage() { echo "usage: $(basename "$0") [--cli <path>] [--name <cli-name>] [--baseline-cli <path>] [--suite <suite>] [--json <path>] [--zip <path>] [--verbose] [--debug]"; }
TEST_CLI="git"
+TEST_CLI_NAME=
BASELINE_CLI=
SUITE=
JSON_RESULT=
@@ -22,6 +23,9 @@ for a in "$@"; do
if [ "${NEXT}" = "cli" ]; then
TEST_CLI="${a}"
NEXT=
+ elif [ "${NEXT}" = "name" ]; then
+ TEST_CLI_NAME="${a}"
+ NEXT=
elif [ "${NEXT}" = "baseline-cli" ]; then
BASELINE_CLI="${a}"
NEXT=
@@ -41,6 +45,10 @@ for a in "$@"; do
NEXT="cli"
elif [[ "${a}" == "-c"* ]]; then
TEST_CLI="${a/-c/}"
+ elif [ "${a}" = "n" ] || [ "${a}" = "--name" ]; then
+ NEXT="name"
+ elif [[ "${a}" == "-n"* ]]; then
+ TEST_CLI_NAME="${a/-n/}"
elif [ "${a}" = "b" ] || [ "${a}" = "--baseline-cli" ]; then
NEXT="baseline-cli"
elif [[ "${a}" == "-b"* ]]; then
diff --git a/tests/clar/clar.c b/tests/clar/clar.c
index c9c3fde..9695dc9 100644
--- a/tests/clar/clar.c
+++ b/tests/clar/clar.c
@@ -41,9 +41,6 @@
# ifndef strdup
# define strdup(str) _strdup(str)
# endif
-# ifndef strcasecmp
-# define strcasecmp(a,b) _stricmp(a,b)
-# endif
# ifndef __MINGW32__
# pragma comment(lib, "shell32")
@@ -94,8 +91,10 @@
static void fs_rm(const char *_source);
static void fs_copy(const char *_source, const char *dest);
+#ifdef CLAR_FIXTURE_PATH
static const char *
fixture_path(const char *base, const char *fixture_name);
+#endif
struct clar_error {
const char *file;
diff --git a/tests/clar/clar/fixtures.h b/tests/clar/clar/fixtures.h
index 77033d3..6ec6423 100644
--- a/tests/clar/clar/fixtures.h
+++ b/tests/clar/clar/fixtures.h
@@ -1,3 +1,4 @@
+#ifdef CLAR_FIXTURE_PATH
static const char *
fixture_path(const char *base, const char *fixture_name)
{
@@ -20,7 +21,6 @@ fixture_path(const char *base, const char *fixture_name)
return _path;
}
-#ifdef CLAR_FIXTURE_PATH
const char *cl_fixture(const char *fixture_name)
{
return fixture_path(CLAR_FIXTURE_PATH, fixture_name);
diff --git a/tests/clar/clar/fs.h b/tests/clar/clar/fs.h
index 44ede45..a6eda5e 100644
--- a/tests/clar/clar/fs.h
+++ b/tests/clar/clar/fs.h
@@ -295,7 +295,9 @@ fs_copy(const char *_source, const char *_dest)
void
cl_fs_cleanup(void)
{
+#ifdef CLAR_FIXTURE_PATH
fs_rm(fixture_path(_clar_path, "*"));
+#endif
}
#else
diff --git a/tests/clar/clar/sandbox.h b/tests/clar/clar/sandbox.h
index 0ba1479..0688374 100644
--- a/tests/clar/clar/sandbox.h
+++ b/tests/clar/clar/sandbox.h
@@ -2,7 +2,8 @@
#include <sys/syslimits.h>
#endif
-static char _clar_path[4096 + 1];
+#define CLAR_PATH_MAX 4096
+static char _clar_path[CLAR_PATH_MAX];
static int
is_valid_tmp_path(const char *path)
@@ -35,10 +36,9 @@ find_tmp_path(char *buffer, size_t length)
continue;
if (is_valid_tmp_path(env)) {
-#ifdef __APPLE__
- if (length >= PATH_MAX && realpath(env, buffer) != NULL)
- return 0;
-#endif
+ if (strlen(env) + 1 > CLAR_PATH_MAX)
+ return -1;
+
strncpy(buffer, env, length - 1);
buffer[length - 1] = '\0';
return 0;
@@ -47,10 +47,6 @@ find_tmp_path(char *buffer, size_t length)
/* If the environment doesn't say anything, try to use /tmp */
if (is_valid_tmp_path("/tmp")) {
-#ifdef __APPLE__
- if (length >= PATH_MAX && realpath("/tmp", buffer) != NULL)
- return 0;
-#endif
strncpy(buffer, "/tmp", length - 1);
buffer[length - 1] = '\0';
return 0;
@@ -75,6 +71,34 @@ find_tmp_path(char *buffer, size_t length)
return -1;
}
+static int canonicalize_tmp_path(char *buffer)
+{
+#ifdef _WIN32
+ char tmp[CLAR_PATH_MAX];
+ DWORD ret;
+
+ ret = GetFullPathName(buffer, CLAR_PATH_MAX, tmp, NULL);
+
+ if (ret == 0 || ret > CLAR_PATH_MAX)
+ return -1;
+
+ ret = GetLongPathName(tmp, buffer, CLAR_PATH_MAX);
+
+ if (ret == 0 || ret > CLAR_PATH_MAX)
+ return -1;
+
+ return 0;
+#else
+ char tmp[CLAR_PATH_MAX];
+
+ if (realpath(buffer, tmp) == NULL)
+ return -1;
+
+ strcpy(buffer, tmp);
+ return 0;
+#endif
+}
+
static void clar_unsandbox(void)
{
if (_clar_path[0] == '\0')
@@ -95,7 +119,8 @@ static int build_sandbox_path(void)
size_t len;
- if (find_tmp_path(_clar_path, sizeof(_clar_path)) < 0)
+ if (find_tmp_path(_clar_path, sizeof(_clar_path)) < 0 ||
+ canonicalize_tmp_path(_clar_path) < 0)
return -1;
len = strlen(_clar_path);
diff --git a/tests/clar/clar_libgit2.h b/tests/clar/clar_libgit2.h
index c33b5d2..d8105c8 100644
--- a/tests/clar/clar_libgit2.h
+++ b/tests/clar/clar_libgit2.h
@@ -166,10 +166,27 @@ GIT_INLINE(void) clar__assert_equal_oid(
}
}
+GIT_INLINE(void) clar__assert_equal_oidstr(
+ const char *file, const char *func, int line, const char *desc,
+ const char *one_str, const git_oid *two)
+{
+ git_oid one;
+
+ if (git_oid__fromstr(&one, one_str, git_oid_type(two)) < 0) {
+ clar__fail(file, func, line, desc, "could not parse oid string", 1);
+ } else {
+ clar__assert_equal_oid(file, func, line, desc, &one, two);
+ }
+}
+
#define cl_assert_equal_oid(one, two) \
clar__assert_equal_oid(__FILE__, __func__, __LINE__, \
"OID mismatch: " #one " != " #two, (one), (two))
+#define cl_assert_equal_oidstr(one_str, two) \
+ clar__assert_equal_oidstr(__FILE__, __func__, __LINE__, \
+ "OID mismatch: " #one_str " != " #two, (one_str), (two))
+
/*
* Some utility macros for building long strings
*/
diff --git a/tests/libgit2/attr/repo.c b/tests/libgit2/attr/repo.c
index abd2381..747715b 100644
--- a/tests/libgit2/attr/repo.c
+++ b/tests/libgit2/attr/repo.c
@@ -309,6 +309,31 @@ void test_attr_repo__bare_repo_with_index(void)
cl_assert(GIT_ATTR_IS_UNSPECIFIED(values[3]));
}
+void test_attr_repo__inmemory_repo_without_index(void)
+{
+ const char *names[1] = { "fake" };
+ const char *values[1];
+ git_repository *inmemory;
+ git_index *index = NULL;
+
+ /* setup bare in-memory repo without index */
+#ifdef GIT_EXPERIMENTAL_SHA256
+ cl_git_pass(git_repository_new(&inmemory, GIT_OID_SHA1));
+#else
+ cl_git_pass(git_repository_new(&inmemory));
+#endif
+ cl_assert(git_repository_is_bare(inmemory));
+
+ /* verify repo isn't given an index upfront in future */
+ git_repository_index(&index, inmemory);
+ cl_assert(!index);
+
+ /* check attributes can be queried without error due to missing index */
+ cl_git_pass(git_attr_get_many(values, inmemory, 0, "fake.txt", 1, names));
+
+ git_repository_free(inmemory);
+}
+
void test_attr_repo__sysdir(void)
{
git_str sysdir = GIT_STR_INIT;
diff --git a/tests/libgit2/blame/buffer.c b/tests/libgit2/blame/buffer.c
index 06d5042..456402c 100644
--- a/tests/libgit2/blame/buffer.c
+++ b/tests/libgit2/blame/buffer.c
@@ -17,15 +17,204 @@ void test_blame_buffer__cleanup(void)
git_repository_free(g_repo);
}
+
+void test_blame_buffer__4_edits(void)
+{
+
+ const char *buffer = "\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+xEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+x\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n";
+
+ cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer)));
+ check_blame_hunk_index(g_repo, g_bufferblame, 0, 1, 2, 0, "da237394", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 1, 3, 1, 0, "000000", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 2, 4, 1, 0, "da237394", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 3, 5, 1, 0, "000000", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 4, 6, 1, 0, "63d671eb", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 5, 7, 1, 0, "000000", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 6, 8, 1, 0, "63d671eb", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 7, 9, 1, 0, "000000", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 8, 10, 1, 0, "63d671eb", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 9, 11, 5, 0, "aa06ecca", "b.txt");
+}
+
+void test_blame_buffer__two_added_lines_and_one_modified(void)
+{
+
+ const char *buffer = "\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+x\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+x\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+xBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n";
+
+ cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer)));
+ check_blame_hunk_index(g_repo, g_bufferblame, 0, 1, 3, 0, "da237394", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 1, 4, 1, 0, "000000", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 2, 5, 1, 0, "da237394", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 3, 6, 1, 0, "000000", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 4, 7, 1, 0, "63d671eb", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 5, 8, 1, 0, "000000", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 6, 9, 3, 0, "63d671eb", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 7, 12, 5, 0, "aa06ecca", "b.txt");
+}
+
+void test_blame_buffer__two_added_lines(void)
+{
+
+ const char *buffer = "\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+abc\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+def\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n";
+
+ cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer)));
+ check_blame_hunk_index(g_repo, g_bufferblame, 0, 1, 3, 0, "da237394", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 1, 4, 1, 0, "000000", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 2, 5, 1, 0, "da237394", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 3, 6, 1, 0, "000000", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 4, 7, 5, 0, "63d671eb", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 5, 12, 5, 0, "aa06ecca", "b.txt");
+}
+
+void test_blame_buffer__added_blocks(void)
+{
+
+ const char *buffer = "\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+\n\
+abcdefg\n\
+hijlmno\n\
+pqrstuv\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+abcdefg\n\
+hijlmno\n\
+pqrstuv\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+\n\
+abcdefg\n\
+hijlmno\n\
+pqrstuv\n";
+
+ cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer)));
+ check_blame_hunk_index(g_repo, g_bufferblame, 0, 1, 4, 0, "da237394", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 1, 5, 1, 1, "b99f7ac0", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 3, 0, "000000", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 3, 9, 4, 0, "63d671eb", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 4, 13, 3, 0, "000000", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 5, 16, 5, 0, "aa06ecca", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 6, 21, 3, 0, "000000", "b.txt");
+
+
+}
+
+void test_blame_buffer__overlapping_blocks(void)
+{
+ const char *buffer = "\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+abcdefg\n\
+hijlmno\n\
+pqrstuv\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+\n\
+";
+
+ cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer)));
+
+ check_blame_hunk_index(g_repo, g_bufferblame, 0, 1, 3, 0, "da237394", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 1, 4, 3, 0, "000000", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 2, 7, 4, 0, "63d671eb", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 3, 11, 5, 0, "aa06ecca", "b.txt");
+
+}
+
+void test_blame_buffer__2_add_splits_hunk(void)
+{
+ const char *buffer = "\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+abc\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+abc\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\n";
+
+ cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer)));
+ check_blame_hunk_index(g_repo, g_bufferblame, 0, 1, 2, 0, "da237394", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 1, 3, 1, 0, "00000000", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 2, 4, 2, 0, "da237394", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 3, 6, 1, 1, "b99f7ac0", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 4, 7, 2, 0, "63d671eb", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 5, 9, 1, 0, "00000000", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 6, 10, 3, 0, "63d671eb", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 7, 13, 5, 0, "aa06ecca", "b.txt");
+}
+
void test_blame_buffer__index(void)
{
const git_blame_hunk *hunk;
const char *buffer = "Hello\nWorld!";
- /*
- * We need to open a different file from the ones used in other tests. Close
- * the one opened in test_blame_buffer__initialize() to avoid a leak.
- */
git_blame_free(g_fileblame);
g_fileblame = NULL;
cl_git_pass(git_blame_file(&g_fileblame, g_repo, "file.txt", NULL));
@@ -43,6 +232,8 @@ void test_blame_buffer__index(void)
cl_assert(hunk->final_signature == NULL);
}
+
+
void test_blame_buffer__added_line(void)
{
const git_blame_hunk *hunk;
@@ -73,6 +264,43 @@ CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
cl_assert_equal_s("Ben Straub", hunk->final_signature->name);
}
+void test_blame_buffer__added_lines(void)
+{
+
+ const char *buffer = "\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n\
+\n\
+\n\
+\n\
+\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n\
+\n\
+\n\
+\n\
+\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC\n\
+\n\
+\n\
+\n\
+\n";
+
+ cl_git_pass(git_blame_buffer(&g_bufferblame, g_fileblame, buffer, strlen(buffer)));
+ cl_assert_equal_i(7, git_blame_get_hunk_count(g_bufferblame));
+ check_blame_hunk_index(g_repo, g_bufferblame, 2, 6, 3, 0, "000000", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 4, 14, 3, 0, "000000", "b.txt");
+ check_blame_hunk_index(g_repo, g_bufferblame, 6, 22, 3, 0, "000000", "b.txt");
+
+}
+
void test_blame_buffer__deleted_line(void)
{
const char *buffer = "\
diff --git a/tests/libgit2/checkout/tree.c b/tests/libgit2/checkout/tree.c
index 65df00c..97935aa 100644
--- a/tests/libgit2/checkout/tree.c
+++ b/tests/libgit2/checkout/tree.c
@@ -1235,7 +1235,7 @@ void test_checkout_tree__case_changing_rename(void)
cl_git_pass(git_signature_new(&signature, "Renamer", "rename@contoso.com", time(NULL), 0));
- cl_git_pass(git_commit_create(&commit_id, g_repo, "refs/heads/dir", signature, signature, NULL, "case-changing rename", tree, 1, (const git_commit **)&dir_commit));
+ cl_git_pass(git_commit_create(&commit_id, g_repo, "refs/heads/dir", signature, signature, NULL, "case-changing rename", tree, 1, &dir_commit));
cl_assert(git_fs_path_isfile("testrepo/readme"));
if (case_sensitive)
diff --git a/tests/libgit2/cherrypick/workdir.c b/tests/libgit2/cherrypick/workdir.c
index c16b781..9d9a3f4 100644
--- a/tests/libgit2/cherrypick/workdir.c
+++ b/tests/libgit2/cherrypick/workdir.c
@@ -77,7 +77,7 @@ void test_cherrypick_workdir__automerge(void)
cl_git_pass(git_index_write_tree(&cherrypicked_tree_oid, repo_index));
cl_git_pass(git_tree_lookup(&cherrypicked_tree, repo, &cherrypicked_tree_oid));
cl_git_pass(git_commit_create(&cherrypicked_oid, repo, "HEAD", signature, signature, NULL,
- "Cherry picked!", cherrypicked_tree, 1, (const git_commit **)&head));
+ "Cherry picked!", cherrypicked_tree, 1, &head));
cl_assert(merge_test_index(repo_index, merge_index_entries + i * 3, 3));
diff --git a/tests/libgit2/clone/local.c b/tests/libgit2/clone/local.c
index e0bd74d..d35fe86 100644
--- a/tests/libgit2/clone/local.c
+++ b/tests/libgit2/clone/local.c
@@ -210,3 +210,13 @@ void test_clone_local__git_style_unc_paths(void)
cl_git_pass(git_futils_rmdir_r("./clone.git", NULL, GIT_RMDIR_REMOVE_FILES));
#endif
}
+
+void test_clone_local__shallow_fails(void)
+{
+ git_repository *repo;
+ git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
+
+ opts.fetch_opts.depth = 4;
+
+ cl_git_fail_with(GIT_ENOTSUPPORTED, git_clone(&repo, cl_fixture("testrepo.git"), "./clone.git", &opts));
+}
diff --git a/tests/libgit2/commit/commit.c b/tests/libgit2/commit/commit.c
index 140f87d..923740f 100644
--- a/tests/libgit2/commit/commit.c
+++ b/tests/libgit2/commit/commit.c
@@ -36,11 +36,11 @@ void test_commit_commit__create_unexisting_update_ref(void)
cl_git_fail(git_reference_lookup(&ref, _repo, "refs/heads/foo/bar"));
cl_git_pass(git_commit_create(&oid, _repo, "refs/heads/foo/bar", s, s,
- NULL, "some msg", tree, 1, (const git_commit **) &commit));
+ NULL, "some msg", tree, 1, &commit));
/* fail because the parent isn't the tip of the branch anymore */
cl_git_fail(git_commit_create(&oid, _repo, "refs/heads/foo/bar", s, s,
- NULL, "some msg", tree, 1, (const git_commit **) &commit));
+ NULL, "some msg", tree, 1, &commit));
cl_git_pass(git_reference_lookup(&ref, _repo, "refs/heads/foo/bar"));
cl_assert_equal_oid(&oid, git_reference_target(ref));
diff --git a/tests/libgit2/commit/create.c b/tests/libgit2/commit/create.c
new file mode 100644
index 0000000..9f627dc
--- /dev/null
+++ b/tests/libgit2/commit/create.c
@@ -0,0 +1,112 @@
+#include "clar_libgit2.h"
+#include "repository.h"
+
+/* Fixture setup */
+static git_repository *g_repo;
+static git_signature *g_author, *g_committer;
+
+void test_commit_create__initialize(void)
+{
+ g_repo = cl_git_sandbox_init("testrepo2");
+ cl_git_pass(git_signature_new(&g_author, "Edward Thomson", "ethomson@edwardthomson.com", 123456789, 60));
+ cl_git_pass(git_signature_new(&g_committer, "libgit2 user", "nobody@noreply.libgit2.org", 987654321, 90));
+}
+
+void test_commit_create__cleanup(void)
+{
+ git_signature_free(g_committer);
+ git_signature_free(g_author);
+ cl_git_sandbox_cleanup();
+}
+
+
+void test_commit_create__from_stage_simple(void)
+{
+ git_commit_create_options opts = GIT_COMMIT_CREATE_OPTIONS_INIT;
+ git_index *index;
+ git_oid commit_id;
+ git_tree *tree;
+
+ opts.author = g_author;
+ opts.committer = g_committer;
+
+ cl_git_rewritefile("testrepo2/newfile.txt", "This is a new file.\n");
+ cl_git_rewritefile("testrepo2/newfile2.txt", "This is a new file.\n");
+ cl_git_rewritefile("testrepo2/README", "hello, world.\n");
+ cl_git_rewritefile("testrepo2/new.txt", "hi there.\n");
+
+ cl_git_pass(git_repository_index(&index, g_repo));
+ cl_git_pass(git_index_add_bypath(index, "newfile2.txt"));
+ cl_git_pass(git_index_add_bypath(index, "README"));
+ cl_git_pass(git_index_write(index));
+
+ cl_git_pass(git_commit_create_from_stage(&commit_id, g_repo, "This is the message.", &opts));
+
+ cl_git_pass(git_repository_head_tree(&tree, g_repo));
+
+ cl_assert_equal_oidstr("241b5b04e847bc38dd7b4b9f49f21e55da40f3a6", &commit_id);
+ cl_assert_equal_oidstr("b27210772d0633870b4f486d04ed3eb5ebbef5e7", git_tree_id(tree));
+
+ git_index_free(index);
+ git_tree_free(tree);
+}
+
+void test_commit_create__from_stage_nochanges(void)
+{
+ git_commit_create_options opts = GIT_COMMIT_CREATE_OPTIONS_INIT;
+ git_oid commit_id;
+ git_tree *tree;
+
+ opts.author = g_author;
+ opts.committer = g_committer;
+
+ cl_git_fail_with(GIT_EUNCHANGED, git_commit_create_from_stage(&commit_id, g_repo, "Message goes here.", &opts));
+
+ opts.allow_empty_commit = 1;
+
+ cl_git_pass(git_commit_create_from_stage(&commit_id, g_repo, "Message goes here.", &opts));
+
+ cl_git_pass(git_repository_head_tree(&tree, g_repo));
+
+ cl_assert_equal_oidstr("f776dc4c7fd8164b7127dc8e4f9b44421cb01b56", &commit_id);
+ cl_assert_equal_oidstr("c4dc1555e4d4fa0e0c9c3fc46734c7c35b3ce90b", git_tree_id(tree));
+
+ git_tree_free(tree);
+}
+
+void test_commit_create__from_stage_newrepo(void)
+{
+ git_commit_create_options opts = GIT_COMMIT_CREATE_OPTIONS_INIT;
+ git_repository *newrepo;
+ git_index *index;
+ git_commit *commit;
+ git_tree *tree;
+ git_oid commit_id;
+
+ opts.author = g_author;
+ opts.committer = g_committer;
+
+ git_repository_init(&newrepo, "newrepo", false);
+ cl_git_pass(git_repository_index(&index, newrepo));
+
+ cl_git_rewritefile("newrepo/hello.txt", "hello, world.\n");
+ cl_git_rewritefile("newrepo/hi.txt", "hi there.\n");
+ cl_git_rewritefile("newrepo/foo.txt", "bar.\n");
+
+ cl_git_pass(git_index_add_bypath(index, "hello.txt"));
+ cl_git_pass(git_index_add_bypath(index, "foo.txt"));
+ cl_git_pass(git_index_write(index));
+
+ cl_git_pass(git_commit_create_from_stage(&commit_id, newrepo, "Initial commit.", &opts));
+ cl_git_pass(git_repository_head_commit(&commit, newrepo));
+ cl_git_pass(git_repository_head_tree(&tree, newrepo));
+
+ cl_assert_equal_oid(&commit_id, git_commit_id(commit));
+ cl_assert_equal_oidstr("b2fa96a4f191c76eb172437281c66aa29609dcaa", git_commit_tree_id(commit));
+
+ git_tree_free(tree);
+ git_commit_free(commit);
+ git_index_free(index);
+ git_repository_free(newrepo);
+ cl_fixture_cleanup("newrepo");
+}
diff --git a/tests/libgit2/commit/signature.c b/tests/libgit2/commit/signature.c
index a915514..fddd507 100644
--- a/tests/libgit2/commit/signature.c
+++ b/tests/libgit2/commit/signature.c
@@ -36,10 +36,17 @@ void test_commit_signature__leading_and_trailing_spaces_are_trimmed(void)
assert_name_and_email("nulltoken", "emeric.fermas@gmail.com", " \t nulltoken \n", " \n emeric.fermas@gmail.com \n");
}
+void test_commit_signature__leading_and_trailing_dots_are_supported(void)
+{
+ assert_name_and_email(".nulltoken", ".emeric.fermas@gmail.com", ".nulltoken", ".emeric.fermas@gmail.com");
+ assert_name_and_email("nulltoken.", "emeric.fermas@gmail.com.", "nulltoken.", "emeric.fermas@gmail.com.");
+ assert_name_and_email(".nulltoken.", ".emeric.fermas@gmail.com.", ".nulltoken.", ".emeric.fermas@gmail.com.");
+}
+
void test_commit_signature__leading_and_trailing_crud_is_trimmed(void)
{
assert_name_and_email("nulltoken", "emeric.fermas@gmail.com", "\"nulltoken\"", "\"emeric.fermas@gmail.com\"");
- assert_name_and_email("nulltoken w", "emeric.fermas@gmail.com", "nulltoken w.", "emeric.fermas@gmail.com");
+ assert_name_and_email("nulltoken w", "emeric.fermas@gmail.com", "nulltoken w;", "emeric.fermas@gmail.com");
assert_name_and_email("nulltoken \xe2\x98\xba", "emeric.fermas@gmail.com", "nulltoken \xe2\x98\xba", "emeric.fermas@gmail.com");
}
diff --git a/tests/libgit2/commit/write.c b/tests/libgit2/commit/write.c
index 890f738..d38b54d 100644
--- a/tests/libgit2/commit/write.c
+++ b/tests/libgit2/commit/write.c
@@ -118,7 +118,7 @@ void test_commit_write__into_buf(void)
cl_git_pass(git_commit_lookup(&parent, g_repo, &parent_id));
cl_git_pass(git_commit_create_buffer(&commit, g_repo, author, committer,
- NULL, root_commit_message, tree, 1, (const git_commit **) &parent));
+ NULL, root_commit_message, tree, 1, &parent));
cl_assert_equal_s(commit.ptr,
"tree 1810dff58d8a660512d4832e740f692884338ccd\n\
diff --git a/tests/libgit2/config/configlevel.c b/tests/libgit2/config/configlevel.c
index 8422d32..0e31268 100644
--- a/tests/libgit2/config/configlevel.c
+++ b/tests/libgit2/config/configlevel.c
@@ -71,3 +71,44 @@ void test_config_configlevel__fetching_a_level_from_an_empty_compound_config_ret
git_config_free(cfg);
}
+
+void test_config_configlevel__can_fetch_highest_level(void)
+{
+ git_config *cfg;
+ git_config *single_level_cfg;
+ git_buf buf = {0};
+
+ cl_git_pass(git_config_new(&cfg));
+ cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config18"),
+ GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
+ cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config19"),
+ GIT_CONFIG_LEVEL_LOCAL, NULL, 0));
+
+ cl_git_pass(git_config_open_level(&single_level_cfg, cfg, GIT_CONFIG_HIGHEST_LEVEL));
+
+ git_config_free(cfg);
+
+ cl_git_pass(git_config_get_string_buf(&buf, single_level_cfg, "core.stringglobal"));
+ cl_assert_equal_s("don't find me!", buf.ptr);
+
+ git_buf_dispose(&buf);
+ git_config_free(single_level_cfg);
+}
+
+void test_config_configlevel__can_override_local_with_worktree(void)
+{
+ git_config *cfg;
+ git_buf buf = GIT_BUF_INIT;
+
+ cl_git_pass(git_config_new(&cfg));
+ cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config19"),
+ GIT_CONFIG_LEVEL_WORKTREE, NULL, 1));
+ cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config18"),
+ GIT_CONFIG_LEVEL_LOCAL, NULL, 1));
+
+ cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.stringglobal"));
+ cl_assert_equal_s("don't find me!", buf.ptr);
+
+ git_buf_dispose(&buf);
+ git_config_free(cfg);
+}
diff --git a/tests/libgit2/config/include.c b/tests/libgit2/config/include.c
index 1b55fdc..ba8bcad 100644
--- a/tests/libgit2/config/include.c
+++ b/tests/libgit2/config/include.c
@@ -111,7 +111,7 @@ void test_config_include__missing(void)
git_error_clear();
cl_git_pass(git_config_open_ondisk(&cfg, "including"));
- cl_assert(git_error_last() == NULL);
+ cl_assert_equal_i(GIT_ERROR_NONE, git_error_last()->klass);
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar"));
cl_assert_equal_s("baz", buf.ptr);
@@ -126,7 +126,7 @@ void test_config_include__missing_homedir(void)
git_error_clear();
cl_git_pass(git_config_open_ondisk(&cfg, "including"));
- cl_assert(git_error_last() == NULL);
+ cl_assert_equal_i(GIT_ERROR_NONE, git_error_last()->klass);
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar"));
cl_assert_equal_s("baz", buf.ptr);
diff --git a/tests/libgit2/config/memory.c b/tests/libgit2/config/memory.c
index ae66189..9f533e2 100644
--- a/tests/libgit2/config/memory.c
+++ b/tests/libgit2/config/memory.c
@@ -34,8 +34,13 @@ static int contains_all_cb(const git_config_entry *entry, void *payload)
int i;
for (i = 0; entries[i].name; i++) {
- if (strcmp(entries[i].name, entry->name) ||
- strcmp(entries[i].value , entry->value))
+ if (strcmp(entries[i].name, entry->name))
+ continue;
+
+ if ((entries[i].value == NULL) ^ (entry->value == NULL))
+ continue;
+
+ if (entry->value && strcmp(entries[i].value , entry->value))
continue;
if (entries[i].seen)
@@ -61,7 +66,23 @@ static void assert_config_contains_all(git_config_backend *backend,
static void setup_backend(const char *cfg)
{
- cl_git_pass(git_config_backend_from_string(&backend, cfg, strlen(cfg)));
+ git_config_backend_memory_options opts =
+ GIT_CONFIG_BACKEND_MEMORY_OPTIONS_INIT;
+
+ opts.backend_type = "test";
+
+ cl_git_pass(git_config_backend_from_string(&backend, cfg, strlen(cfg), &opts));
+ cl_git_pass(git_config_backend_open(backend, 0, NULL));
+}
+
+static void setup_values_backend(const char **values, size_t len)
+{
+ git_config_backend_memory_options opts =
+ GIT_CONFIG_BACKEND_MEMORY_OPTIONS_INIT;
+
+ opts.backend_type = "test";
+
+ cl_git_pass(git_config_backend_from_values(&backend, values, len, &opts));
cl_git_pass(git_config_backend_open(backend, 0, NULL));
}
@@ -88,7 +109,13 @@ void test_config_memory__malformed_fails_to_open(void)
const char *cfg =
"[general\n"
"foo=bar\n";
- cl_git_pass(git_config_backend_from_string(&backend, cfg, strlen(cfg)));
+
+ git_config_backend_memory_options opts =
+ GIT_CONFIG_BACKEND_MEMORY_OPTIONS_INIT;
+
+ opts.backend_type = "test";
+
+ cl_git_pass(git_config_backend_from_string(&backend, cfg, strlen(cfg), &opts));
cl_git_fail(git_config_backend_open(backend, 0, NULL));
}
@@ -137,3 +164,43 @@ void test_config_memory__foreach_sees_multivar(void)
"foo=bar2\n");
assert_config_contains_all(backend, entries);
}
+
+void test_config_memory__values(void)
+{
+ const char *values[] = {
+ "general.foo=bar1",
+ "general.foo=bar2",
+ "other.key=value",
+ "empty.value=",
+ "no.value",
+ };
+
+ struct expected_entry entries[] = {
+ { "general.foo", "bar1", 0 },
+ { "general.foo", "bar2", 0 },
+ { "other.key", "value", 0 },
+ { "empty.value", "", 0 },
+ { "no.value", NULL, 0 },
+ { NULL, NULL, 0 }
+ };
+
+ setup_values_backend(values, 5);
+ assert_config_contains_all(backend, entries);
+}
+
+void test_config_memory__valid_values(void)
+{
+ const char *values[] = {
+ "general.foo=bar1",
+ "=bar2",
+ "other.key=value"
+ };
+
+ git_config_backend_memory_options opts =
+ GIT_CONFIG_BACKEND_MEMORY_OPTIONS_INIT;
+
+ opts.backend_type = "test";
+
+ cl_git_pass(git_config_backend_from_values(&backend, values, 3, &opts));
+ cl_git_fail(git_config_backend_open(backend, 0, NULL));
+}
diff --git a/tests/libgit2/config/multivar.c b/tests/libgit2/config/multivar.c
index 244e375..3ed8460 100644
--- a/tests/libgit2/config/multivar.c
+++ b/tests/libgit2/config/multivar.c
@@ -1,4 +1,6 @@
#include "clar_libgit2.h"
+#include "config.h"
+#include "config/config_helpers.h"
static const char *_name = "remote.ab.url";
@@ -286,3 +288,32 @@ void test_config_multivar__delete_notfound(void)
git_config_free(cfg);
}
+
+void test_config_multivar__rename_section(void)
+{
+ git_repository *repo;
+ git_config *cfg;
+ int n;
+
+ repo = cl_git_sandbox_init("testrepo");
+ cl_git_pass(git_repository_config(&cfg, repo));
+
+ cl_git_pass(git_config_set_multivar(cfg, "branch.foo.name", "^$", "bar"));
+ cl_git_pass(git_config_set_multivar(cfg, "branch.foo.name", "^$", "xyzzy"));
+ n = 0;
+ cl_git_pass(git_config_get_multivar_foreach(
+ cfg, "branch.foo.name", NULL, cb, &n));
+ cl_assert(n == 2);
+
+ cl_git_pass(
+ git_config_rename_section(repo, "branch.foo", "branch.foobar"));
+
+ assert_config_entry_existence(repo, "branch.foo.name", false);
+ n = 0;
+ cl_git_pass(git_config_get_multivar_foreach(
+ cfg, "branch.foobar.name", NULL, cb, &n));
+ cl_assert(n == 2);
+
+ git_config_free(cfg);
+ cl_git_sandbox_cleanup();
+}
diff --git a/tests/libgit2/config/read.c b/tests/libgit2/config/read.c
index ac6459b..25e7b96 100644
--- a/tests/libgit2/config/read.c
+++ b/tests/libgit2/config/read.c
@@ -495,6 +495,8 @@ void test_config_read__read_git_config_entry(void)
cl_assert_equal_s("core.dummy2", entry->name);
cl_assert_equal_s("42", entry->value);
cl_assert_equal_i(GIT_CONFIG_LEVEL_SYSTEM, entry->level);
+ cl_assert_equal_s("file", entry->backend_type);
+ cl_assert_equal_s(cl_fixture("config/config9"), entry->origin_path);
git_config_entry_free(entry);
git_config_free(cfg);
diff --git a/tests/libgit2/config/readonly.c b/tests/libgit2/config/readonly.c
index a8901e3..483f83a 100644
--- a/tests/libgit2/config/readonly.c
+++ b/tests/libgit2/config/readonly.c
@@ -24,7 +24,7 @@ void test_config_readonly__writing_to_readonly_fails(void)
backend->readonly = 1;
cl_git_pass(git_config_add_backend(cfg, backend, GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
- cl_git_fail_with(GIT_ENOTFOUND, git_config_set_string(cfg, "foo.bar", "baz"));
+ cl_git_fail_with(GIT_EREADONLY, git_config_set_string(cfg, "foo.bar", "baz"));
cl_assert(!git_fs_path_exists("global"));
}
diff --git a/tests/libgit2/config/snapshot.c b/tests/libgit2/config/snapshot.c
index 5cc08a7..cc87706 100644
--- a/tests/libgit2/config/snapshot.c
+++ b/tests/libgit2/config/snapshot.c
@@ -79,6 +79,7 @@ void test_config_snapshot__multivar(void)
void test_config_snapshot__includes(void)
{
+ git_config_entry *entry;
int i;
cl_git_mkfile("including", "[include]\npath = included");
@@ -99,6 +100,16 @@ void test_config_snapshot__includes(void)
cl_git_pass(git_config_get_int32(&i, snapshot, "section.key"));
cl_assert_equal_i(i, 1);
+ /* Ensure that the config entry is populated with origin */
+ cl_git_pass(git_config_get_entry(&entry, snapshot, "section.key"));
+
+ cl_assert_equal_s("section.key", entry->name);
+ cl_assert_equal_s("1", entry->value);
+ cl_assert_equal_s("file", entry->backend_type);
+ cl_assert_equal_s("./included", entry->origin_path);
+
+ git_config_entry_free(entry);
+
cl_git_pass(p_unlink("including"));
cl_git_pass(p_unlink("included"));
}
@@ -106,6 +117,7 @@ void test_config_snapshot__includes(void)
void test_config_snapshot__snapshot(void)
{
git_config *snapshot_snapshot;
+ git_config_entry *entry;
int i;
cl_git_mkfile("configfile", "[section]\nkey = 1\n");
@@ -118,22 +130,49 @@ void test_config_snapshot__snapshot(void)
cl_git_pass(git_config_get_int32(&i, snapshot_snapshot, "section.key"));
cl_assert_equal_i(i, 1);
+ /* Ensure that the config entry is populated with origin */
+ cl_git_pass(git_config_get_entry(&entry, snapshot_snapshot, "section.key"));
+
+ cl_assert_equal_s("section.key", entry->name);
+ cl_assert_equal_s("1", entry->value);
+ cl_assert_equal_s("file", entry->backend_type);
+ cl_assert_equal_s("configfile", entry->origin_path);
+
+ git_config_entry_free(entry);
+
git_config_free(snapshot_snapshot);
cl_git_pass(p_unlink("configfile"));
}
-void test_config_snapshot__snapshot_from_in_memony(void)
+void test_config_snapshot__snapshot_from_in_memory(void)
{
const char *configuration = "[section]\nkey = 1\n";
git_config_backend *backend;
+ git_config_entry *entry;
int i;
+ git_config_backend_memory_options opts =
+ GIT_CONFIG_BACKEND_MEMORY_OPTIONS_INIT;
+
+ opts.backend_type = "test";
+ opts.origin_path = "hello";
+
cl_git_pass(git_config_new(&cfg));
- cl_git_pass(git_config_backend_from_string(&backend, configuration, strlen(configuration)));
+ cl_git_pass(git_config_backend_from_string(&backend, configuration, strlen(configuration), &opts));
cl_git_pass(git_config_add_backend(cfg, backend, 0, NULL, 0));
cl_git_pass(git_config_snapshot(&snapshot, cfg));
cl_git_pass(git_config_get_int32(&i, snapshot, "section.key"));
cl_assert_equal_i(i, 1);
+
+ /* Ensure that the config entry is populated with origin */
+ cl_git_pass(git_config_get_entry(&entry, snapshot, "section.key"));
+
+ cl_assert_equal_s("section.key", entry->name);
+ cl_assert_equal_s("1", entry->value);
+ cl_assert_equal_s("test", entry->backend_type);
+ cl_assert_equal_s("hello", entry->origin_path);
+
+ git_config_entry_free(entry);
}
diff --git a/tests/libgit2/config/write.c b/tests/libgit2/config/write.c
index 9d8c3fe..c71d4f6 100644
--- a/tests/libgit2/config/write.c
+++ b/tests/libgit2/config/write.c
@@ -696,6 +696,36 @@ void test_config_write__locking(void)
git_config_free(cfg);
}
+void test_config_write__abort_lock(void)
+{
+ git_config *cfg;
+ git_config_entry *entry;
+ git_transaction *tx;
+ const char *filename = "locked-file";
+
+ /* Open the config and lock it */
+ cl_git_mkfile(filename, "[section]\n\tname = value\n");
+ cl_git_pass(git_config_open_ondisk(&cfg, filename));
+ cl_git_pass(git_config_get_entry(&entry, cfg, "section.name"));
+ cl_assert_equal_s("value", entry->value);
+ git_config_entry_free(entry);
+ cl_git_pass(git_config_lock(&tx, cfg));
+
+ /* Change entries in the locked backend */
+ cl_git_pass(git_config_set_string(cfg, "section.name", "other value"));
+ cl_git_pass(git_config_set_string(cfg, "section2.name3", "more value"));
+
+ git_transaction_free(tx);
+
+ /* Now that we've unlocked it, we should see no changes */
+ cl_git_pass(git_config_get_entry(&entry, cfg, "section.name"));
+ cl_assert_equal_s("value", entry->value);
+ git_config_entry_free(entry);
+ cl_git_fail_with(GIT_ENOTFOUND, git_config_get_entry(&entry, cfg, "section2.name3"));
+
+ git_config_free(cfg);
+}
+
void test_config_write__repeated(void)
{
const char *filename = "config-repeated";
diff --git a/tests/libgit2/core/opts.c b/tests/libgit2/core/opts.c
index 1aa095a..cbef29f 100644
--- a/tests/libgit2/core/opts.c
+++ b/tests/libgit2/core/opts.c
@@ -34,9 +34,10 @@ void test_core_opts__extensions_query(void)
cl_git_pass(git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, &out));
- cl_assert_equal_sz(out.count, 2);
+ cl_assert_equal_sz(out.count, 3);
cl_assert_equal_s("noop", out.strings[0]);
cl_assert_equal_s("objectformat", out.strings[1]);
+ cl_assert_equal_s("worktreeconfig", out.strings[2]);
git_strarray_dispose(&out);
}
@@ -49,10 +50,11 @@ void test_core_opts__extensions_add(void)
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, in, ARRAY_SIZE(in)));
cl_git_pass(git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, &out));
- cl_assert_equal_sz(out.count, 3);
+ cl_assert_equal_sz(out.count, 4);
cl_assert_equal_s("foo", out.strings[0]);
cl_assert_equal_s("noop", out.strings[1]);
cl_assert_equal_s("objectformat", out.strings[2]);
+ cl_assert_equal_s("worktreeconfig", out.strings[3]);
git_strarray_dispose(&out);
}
@@ -65,10 +67,11 @@ void test_core_opts__extensions_remove(void)
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, in, ARRAY_SIZE(in)));
cl_git_pass(git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, &out));
- cl_assert_equal_sz(out.count, 3);
+ cl_assert_equal_sz(out.count, 4);
cl_assert_equal_s("bar", out.strings[0]);
cl_assert_equal_s("baz", out.strings[1]);
cl_assert_equal_s("objectformat", out.strings[2]);
+ cl_assert_equal_s("worktreeconfig", out.strings[3]);
git_strarray_dispose(&out);
}
@@ -81,11 +84,12 @@ void test_core_opts__extensions_uniq(void)
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_EXTENSIONS, in, ARRAY_SIZE(in)));
cl_git_pass(git_libgit2_opts(GIT_OPT_GET_EXTENSIONS, &out));
- cl_assert_equal_sz(out.count, 4);
+ cl_assert_equal_sz(out.count, 5);
cl_assert_equal_s("bar", out.strings[0]);
cl_assert_equal_s("foo", out.strings[1]);
cl_assert_equal_s("noop", out.strings[2]);
cl_assert_equal_s("objectformat", out.strings[3]);
+ cl_assert_equal_s("worktreeconfig", out.strings[4]);
git_strarray_dispose(&out);
}
diff --git a/tests/libgit2/core/useragent.c b/tests/libgit2/core/useragent.c
index a4ece90..2e119de 100644
--- a/tests/libgit2/core/useragent.c
+++ b/tests/libgit2/core/useragent.c
@@ -1,17 +1,52 @@
#include "clar_libgit2.h"
#include "settings.h"
-void test_core_useragent__get(void)
+static git_buf default_ua = GIT_BUF_INIT;
+static git_buf default_product = GIT_BUF_INIT;
+
+void test_core_useragent__initialize(void)
+{
+ cl_git_pass(git_libgit2_opts(GIT_OPT_GET_USER_AGENT, &default_ua));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_GET_USER_AGENT_PRODUCT, &default_product));
+}
+
+void test_core_useragent__cleanup(void)
+{
+ git_libgit2_opts(GIT_OPT_SET_USER_AGENT, NULL);
+ git_libgit2_opts(GIT_OPT_SET_USER_AGENT_PRODUCT, NULL);
+
+ git_buf_dispose(&default_ua);
+ git_buf_dispose(&default_product);
+}
+
+void test_core_useragent__get_default(void)
+{
+ cl_assert(default_ua.size);
+ cl_assert(default_ua.ptr);
+ cl_assert(git__prefixcmp(default_ua.ptr, "libgit2 ") == 0);
+
+ cl_assert(default_product.size);
+ cl_assert(default_product.ptr);
+ cl_assert(git__prefixcmp(default_product.ptr, "git/") == 0);
+}
+
+void test_core_useragent__set(void)
{
- const char *custom_name = "super duper git";
- git_str buf = GIT_STR_INIT;
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_USER_AGENT, "foo bar 4.24"));
+ cl_assert_equal_s("foo bar 4.24", git_settings__user_agent());
+ cl_assert_equal_s(default_product.ptr, git_settings__user_agent_product());
- cl_assert_equal_p(NULL, git_libgit2__user_agent());
- cl_git_pass(git_libgit2_opts(GIT_OPT_SET_USER_AGENT, custom_name));
- cl_assert_equal_s(custom_name, git_libgit2__user_agent());
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_USER_AGENT_PRODUCT, "baz/2.2.3"));
+ cl_assert_equal_s("foo bar 4.24", git_settings__user_agent());
+ cl_assert_equal_s("baz/2.2.3", git_settings__user_agent_product());
- cl_git_pass(git_libgit2_opts(GIT_OPT_GET_USER_AGENT, &buf));
- cl_assert_equal_s(custom_name, buf.ptr);
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_USER_AGENT, ""));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_USER_AGENT_PRODUCT, ""));
+ cl_assert_equal_s("", git_settings__user_agent());
+ cl_assert_equal_s("", git_settings__user_agent_product());
- git_str_dispose(&buf);
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_USER_AGENT, NULL));
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_USER_AGENT_PRODUCT, NULL));
+ cl_assert_equal_s(default_ua.ptr, git_settings__user_agent());
+ cl_assert_equal_s(default_product.ptr, git_settings__user_agent_product());
}
diff --git a/tests/libgit2/diff/parse.c b/tests/libgit2/diff/parse.c
index 79745b9..59fc028 100644
--- a/tests/libgit2/diff/parse.c
+++ b/tests/libgit2/diff/parse.c
@@ -279,6 +279,31 @@ static int file_cb(const git_diff_delta *delta, float progress, void *payload)
return 0;
}
+void test_diff_parse__eof_nl_missing(void)
+{
+ const char patch[] =
+ "diff --git a/.env b/.env\n"
+ "index f89e4c0..7c56eb7 100644\n"
+ "--- a/.env\n"
+ "+++ b/.env\n"
+ "@@ -1 +1 @@\n"
+ "-hello=12345\n"
+ "+hello=123456\n"
+ "\\ No newline at end of file\n";
+ git_diff *diff;
+ git_patch *ret_patch;
+ git_diff_line *line;
+
+ cl_git_pass(diff_from_buffer(&diff, patch, strlen(patch)));
+ cl_git_pass(git_patch_from_diff(&ret_patch, diff, 0));
+
+ cl_assert((line = git_array_get(ret_patch->lines, 2)) != NULL);
+ cl_assert(line->origin == GIT_DIFF_LINE_DEL_EOFNL);
+
+ git_diff_free(diff);
+ git_patch_free(ret_patch);
+}
+
void test_diff_parse__foreach_works_with_parsed_patch(void)
{
const char patch[] =
diff --git a/tests/libgit2/diff/rename.c b/tests/libgit2/diff/rename.c
index 9d44394..15dee5c 100644
--- a/tests/libgit2/diff/rename.c
+++ b/tests/libgit2/diff/rename.c
@@ -424,7 +424,7 @@ void test_diff_rename__test_small_files(void)
cl_git_pass(git_index_write_tree(&oid, index));
cl_git_pass(git_tree_lookup(&commit_tree, g_repo, &oid));
cl_git_pass(git_signature_new(&signature, "Rename", "rename@example.com", 1404157834, 0));
- cl_git_pass(git_commit_create(&oid, g_repo, "HEAD", signature, signature, NULL, "Test commit", commit_tree, 1, (const git_commit**)&head_commit));
+ cl_git_pass(git_commit_create(&oid, g_repo, "HEAD", signature, signature, NULL, "Test commit", commit_tree, 1, &head_commit));
cl_git_mkfile("renames/copy.txt", "Hello World!\n");
cl_git_rmfile("renames/small.txt");
@@ -1441,6 +1441,52 @@ void test_diff_rename__can_delete_unmodified_deltas(void)
git_str_dispose(&c1);
}
+void test_diff_rename__can_delete_unmodified_deltas_including_submodule(void)
+{
+ git_repository *repo; /* "submodules" */
+ git_index *index;
+ git_tree *tree;
+ git_diff *diff;
+ git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT;
+ git_diff_find_options opts = GIT_DIFF_FIND_OPTIONS_INIT;
+ diff_expects exp;
+
+ cl_git_sandbox_cleanup(); /* Don't use "renames" for this test */
+ repo = cl_git_sandbox_init("submodules");
+
+ cl_repo_set_bool(repo, "core.autocrlf", false);
+
+ cl_git_pass(
+ git_revparse_single((git_object **)&tree, repo, "HEAD^{tree}"));
+
+ cl_git_pass(git_repository_index(&index, repo));
+ cl_git_pass(git_index_read_tree(index, tree));
+
+ diffopts.flags = GIT_DIFF_INCLUDE_UNMODIFIED;
+
+ cl_git_pass(git_diff_tree_to_index(&diff, repo, tree, index, &diffopts));
+
+ memset(&exp, 0, sizeof(exp));
+ cl_git_pass(git_diff_foreach(
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
+ cl_assert_equal_i(5, exp.files);
+ cl_assert_equal_i(5, exp.file_status[GIT_DELTA_UNMODIFIED]);
+
+ opts.flags = GIT_DIFF_FIND_ALL | GIT_DIFF_FIND_REMOVE_UNMODIFIED;
+ cl_git_pass(git_diff_find_similar(diff, &opts));
+
+ memset(&exp, 0, sizeof(exp));
+ cl_git_pass(git_diff_foreach(
+ diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
+ cl_assert_equal_i(0, exp.files);
+
+ git_diff_free(diff);
+ git_tree_free(tree);
+ git_index_free(index);
+
+ cl_git_sandbox_cleanup();
+}
+
void test_diff_rename__matches_config_behavior(void)
{
const char *sha0 = INITIAL_COMMIT;
diff --git a/tests/libgit2/diff/workdir.c b/tests/libgit2/diff/workdir.c
index c433b75..504ece6 100644
--- a/tests/libgit2/diff/workdir.c
+++ b/tests/libgit2/diff/workdir.c
@@ -2286,42 +2286,81 @@ void test_diff_workdir__to_index_reversed_content_loads(void)
diff_expects exp;
int use_iterator;
char *pathspec = "new_file";
-
+
g_repo = cl_git_sandbox_init("status");
-
+
opts.context_lines = 3;
opts.interhunk_lines = 1;
opts.flags |= GIT_DIFF_INCLUDE_IGNORED | GIT_DIFF_INCLUDE_UNTRACKED |
GIT_DIFF_SHOW_UNTRACKED_CONTENT | GIT_DIFF_REVERSE;
opts.pathspec.strings = &pathspec;
opts.pathspec.count = 1;
-
+
cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
-
+
for (use_iterator = 0; use_iterator <= 1; use_iterator++) {
memset(&exp, 0, sizeof(exp));
-
+
if (use_iterator)
cl_git_pass(diff_foreach_via_iterator(
diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
else
cl_git_pass(git_diff_foreach(
diff, diff_file_cb, diff_binary_cb, diff_hunk_cb, diff_line_cb, &exp));
-
+
cl_assert_equal_i(1, exp.files);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_ADDED]);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_DELETED]);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_MODIFIED]);
cl_assert_equal_i(0, exp.file_status[GIT_DELTA_IGNORED]);
cl_assert_equal_i(1, exp.file_status[GIT_DELTA_UNTRACKED]);
-
+
cl_assert_equal_i(1, exp.hunks);
-
+
cl_assert_equal_i(1, exp.lines);
cl_assert_equal_i(0, exp.line_ctxt);
cl_assert_equal_i(0, exp.line_adds);
cl_assert_equal_i(1, exp.line_dels);
}
-
+
+ git_diff_free(diff);
+}
+
+void test_diff_workdir__completely_ignored_shows_empty_diff(void)
+{
+ git_diff_options opts = GIT_DIFF_OPTIONS_INIT;
+ git_diff *diff;
+ git_patch *patch;
+ git_buf buf = GIT_BUF_INIT;
+ char *pathspec = "subdir.txt";
+
+ opts.pathspec.strings = &pathspec;
+ opts.pathspec.count = 1;
+
+ g_repo = cl_git_sandbox_init("status");
+ cl_git_rewritefile("status/subdir.txt", "Is it a bird?\n\nIs it a plane?\n");
+
+ /* Perform the diff normally */
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
+ cl_git_pass(git_patch_from_diff(&patch, diff, 0));
+ cl_git_pass(git_patch_to_buf(&buf, patch));
+
+ cl_assert_equal_s("diff --git a/subdir.txt b/subdir.txt\nindex e8ee89e..53c8db5 100644\n--- a/subdir.txt\n+++ b/subdir.txt\n@@ -1,2 +1,3 @@\n Is it a bird?\n+\n Is it a plane?\n", buf.ptr);
+
+ git_buf_dispose(&buf);
+ git_patch_free(patch);
+ git_diff_free(diff);
+
+ /* Perform the diff ignoring blank lines */
+ opts.flags |= GIT_DIFF_IGNORE_BLANK_LINES;
+
+ cl_git_pass(git_diff_index_to_workdir(&diff, g_repo, NULL, &opts));
+ cl_git_pass(git_patch_from_diff(&patch, diff, 0));
+ cl_git_pass(git_patch_to_buf(&buf, patch));
+
+ cl_assert_equal_s("", buf.ptr);
+
+ git_buf_dispose(&buf);
+ git_patch_free(patch);
git_diff_free(diff);
}
diff --git a/tests/libgit2/grafts/shallow.c b/tests/libgit2/grafts/shallow.c
index 5911a26..289d1b1 100644
--- a/tests/libgit2/grafts/shallow.c
+++ b/tests/libgit2/grafts/shallow.c
@@ -40,7 +40,7 @@ void test_grafts_shallow__clears_errors(void)
{
g_repo = cl_git_sandbox_init("testrepo.git");
cl_assert_equal_i(0, git_repository_is_shallow(g_repo));
- cl_assert_equal_p(NULL, git_error_last());
+ cl_assert_equal_i(GIT_ERROR_NONE, git_error_last()->klass);
}
void test_grafts_shallow__shallow_oids(void)
diff --git a/tests/libgit2/iterator/workdir.c b/tests/libgit2/iterator/workdir.c
index 7634997..af47d8b 100644
--- a/tests/libgit2/iterator/workdir.c
+++ b/tests/libgit2/iterator/workdir.c
@@ -585,9 +585,9 @@ void test_iterator_workdir__filesystem(void)
expect_iterator_items(i, 5, expect_noauto, 18, expect_trees);
git_iterator_free(i);
- git__tsort((void **)expect_base, 8, (git__tsort_cmp)git__strcasecmp);
- git__tsort((void **)expect_trees, 18, (git__tsort_cmp)git__strcasecmp);
- git__tsort((void **)expect_noauto, 5, (git__tsort_cmp)git__strcasecmp);
+ git__tsort((void **)expect_base, 8, git__strcasecmp_cb);
+ git__tsort((void **)expect_trees, 18, git__strcasecmp_cb);
+ git__tsort((void **)expect_noauto, 5, git__strcasecmp_cb);
i_opts.flags = GIT_ITERATOR_IGNORE_CASE;
cl_git_pass(git_iterator_for_filesystem(&i, "status/subdir", &i_opts));
diff --git a/tests/libgit2/merge/trees/renames.c b/tests/libgit2/merge/trees/renames.c
index a27945e..9507b51 100644
--- a/tests/libgit2/merge/trees/renames.c
+++ b/tests/libgit2/merge/trees/renames.c
@@ -350,3 +350,22 @@ void test_merge_trees_renames__cache_recomputation(void)
git_tree_free(our_tree);
git__free(data);
}
+
+void test_merge_trees_renames__emptyfile_renames(void)
+{
+ git_index *index;
+ git_merge_options *opts = NULL;
+
+ struct merge_index_entry merge_index_entries[] = {
+ { 0100644, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", 1, "bar" },
+ { 0100644, "60b12be2d2f57977ce83d8dfd32e2394ac1ba1a2", 3, "bar" },
+ { 0100644, "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", 0, "boo" },
+ { 0100644, "e50a49f9558d09d4d3bfc108363bb24c127ed263", 0, "foo" },
+ };
+
+ cl_git_pass(merge_trees_from_branches(&index, repo,
+ "emptyfile_renames", "emptyfile_renames-branch",
+ opts));
+ cl_assert(merge_test_index(index, merge_index_entries, 4));
+ git_index_free(index);
+}
diff --git a/tests/libgit2/message/trailer.c b/tests/libgit2/message/trailer.c
index 919e10a..09e8f61 100644
--- a/tests/libgit2/message/trailer.c
+++ b/tests/libgit2/message/trailer.c
@@ -3,19 +3,22 @@
static void assert_trailers(const char *message, git_message_trailer *trailers)
{
git_message_trailer_array arr;
- size_t i;
+ size_t i, count;
int rc = git_message_trailers(&arr, message);
cl_assert_equal_i(0, rc);
- for(i=0; i<arr.count; i++) {
+ for (i = 0, count = 0; trailers[i].key != NULL; i++, count++)
+ ;
+
+ cl_assert_equal_sz(arr.count, count);
+
+ for (i=0; i < count; i++) {
cl_assert_equal_s(arr.trailers[i].key, trailers[i].key);
cl_assert_equal_s(arr.trailers[i].value, trailers[i].value);
}
- cl_assert_equal_i(0, rc);
-
git_message_trailer_array_free(&arr);
}
@@ -162,3 +165,23 @@ void test_message_trailer__invalid(void)
"Another: trailer\n"
, trailers);
}
+
+void test_message_trailer__ignores_dashes(void)
+{
+ git_message_trailer trailers[] = {
+ { "Signed-off-by", "some@one.com" },
+ { "Another", "trailer" },
+ { NULL, NULL },
+ };
+
+ assert_trailers(
+ "Message\n"
+ "\n"
+ "Markdown header\n"
+ "---------------\n"
+ "Lorem ipsum\n"
+ "\n"
+ "Signed-off-by: some@one.com\n"
+ "Another: trailer\n"
+ , trailers);
+}
diff --git a/tests/libgit2/network/remote/local.c b/tests/libgit2/network/remote/local.c
index 2007f37..d70d0eb 100644
--- a/tests/libgit2/network/remote/local.c
+++ b/tests/libgit2/network/remote/local.c
@@ -473,7 +473,11 @@ void test_network_remote_local__anonymous_remote_inmemory_repo(void)
git_str_sets(&file_path_buf, cl_git_path_url(cl_fixture("testrepo.git")));
+#ifdef GIT_EXPERIMENTAL_SHA256
+ cl_git_pass(git_repository_new(&inmemory, GIT_OID_SHA1));
+#else
cl_git_pass(git_repository_new(&inmemory));
+#endif
cl_git_pass(git_remote_create_anonymous(&remote, inmemory, git_str_cstr(&file_path_buf)));
cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL, NULL));
cl_assert(git_remote_connected(remote));
diff --git a/tests/libgit2/network/remote/rename.c b/tests/libgit2/network/remote/rename.c
index b071f9c..21ea216 100644
--- a/tests/libgit2/network/remote/rename.c
+++ b/tests/libgit2/network/remote/rename.c
@@ -216,7 +216,7 @@ void test_network_remote_rename__symref_head(void)
cl_assert_equal_i(0, problems.count);
git_strarray_dispose(&problems);
- cl_git_pass(git_vector_init(&refs, 2, (git_vector_cmp) git_reference_cmp));
+ cl_git_pass(git_vector_init(&refs, 2, git_reference__cmp_cb));
cl_git_pass(git_branch_iterator_new(&iter, _repo, GIT_BRANCH_REMOTE));
while ((error = git_branch_next(&ref, &btype, iter)) == 0) {
diff --git a/tests/libgit2/odb/backend/nobackend.c b/tests/libgit2/odb/backend/nobackend.c
index 7d9394c..a81e585 100644
--- a/tests/libgit2/odb/backend/nobackend.c
+++ b/tests/libgit2/odb/backend/nobackend.c
@@ -11,7 +11,11 @@ void test_odb_backend_nobackend__initialize(void)
git_odb *odb;
git_refdb *refdb;
+#ifdef GIT_EXPERIMENTAL_SHA256
+ cl_git_pass(git_repository_new(&_repo, GIT_OID_SHA1));
+#else
cl_git_pass(git_repository_new(&_repo));
+#endif
cl_git_pass(git_config_new(&config));
cl_git_pass(git_odb__new(&odb, NULL));
cl_git_pass(git_refdb_new(&refdb, _repo));
diff --git a/tests/libgit2/odb/freshen.c b/tests/libgit2/odb/freshen.c
index e337c82..d0e0e3c 100644
--- a/tests/libgit2/odb/freshen.c
+++ b/tests/libgit2/odb/freshen.c
@@ -125,7 +125,7 @@ void test_odb_freshen__tree_during_commit(void)
cl_git_pass(git_commit_create(&commit_id, repo, NULL,
signature, signature, NULL, "New commit pointing to old tree",
- tree, 1, (const git_commit **)&parent));
+ tree, 1, &parent));
/* make sure we freshen the tree the commit points to */
cl_must_pass(p_lstat("testrepo.git/objects/" LOOSE_TREE_FN, &after));
diff --git a/tests/libgit2/odb/sorting.c b/tests/libgit2/odb/sorting.c
index ec4e369..3fe52e8 100644
--- a/tests/libgit2/odb/sorting.c
+++ b/tests/libgit2/odb/sorting.c
@@ -7,6 +7,11 @@ typedef struct {
size_t position;
} fake_backend;
+static void odb_backend_free(git_odb_backend *odb)
+{
+ git__free(odb);
+}
+
static git_odb_backend *new_backend(size_t position)
{
fake_backend *b;
@@ -15,7 +20,7 @@ static git_odb_backend *new_backend(size_t position)
if (b == NULL)
return NULL;
- b->base.free = (void (*)(git_odb_backend *)) git__free;
+ b->base.free = odb_backend_free;
b->base.version = GIT_ODB_BACKEND_VERSION;
b->position = position;
return (git_odb_backend *)b;
diff --git a/tests/libgit2/online/clone.c b/tests/libgit2/online/clone.c
index 5789e96..207dd83 100644
--- a/tests/libgit2/online/clone.c
+++ b/tests/libgit2/online/clone.c
@@ -7,6 +7,7 @@
#include "refs.h"
#define LIVE_REPO_URL "http://github.com/libgit2/TestGitRepository"
+#define LIVE_REPO_AS_DIR "http:/github.com/libgit2/TestGitRepository"
#define LIVE_EMPTYREPO_URL "http://github.com/libgit2/TestEmptyRepository"
#define BB_REPO_URL "https://libgit2-test@bitbucket.org/libgit2-test/testgitrepository.git"
#define BB_REPO_URL_WITH_PASS "https://libgit2-test:YT77Ppm2nq8w4TYjGS8U@bitbucket.org/libgit2-test/testgitrepository.git"
@@ -47,6 +48,9 @@ static char *_orig_http_proxy = NULL;
static char *_orig_https_proxy = NULL;
static char *_orig_no_proxy = NULL;
+static char *_ssh_cmd = NULL;
+static char *_orig_ssh_cmd = NULL;
+
static int ssl_cert(git_cert *cert, int valid, const char *host, void *payload)
{
GIT_UNUSED(cert);
@@ -102,8 +106,26 @@ void test_online_clone__initialize(void)
_orig_https_proxy = cl_getenv("HTTPS_PROXY");
_orig_no_proxy = cl_getenv("NO_PROXY");
+ _orig_ssh_cmd = cl_getenv("GIT_SSH");
+ _ssh_cmd = cl_getenv("GITTEST_SSH_CMD");
+
+ if (_ssh_cmd)
+ cl_setenv("GIT_SSH", _ssh_cmd);
+ else
+ cl_setenv("GIT_SSH", NULL);
+
if (_remote_expectcontinue)
git_libgit2_opts(GIT_OPT_ENABLE_HTTP_EXPECT_CONTINUE, 1);
+
+#if !defined(GIT_WIN32)
+ /*
+ * On system that allows ':' in filenames "http://path" can be misinterpreted
+ * as the local path "http:/path".
+ * Create a local non-repository path that looks like LIVE_REPO_URL to make
+ * sure we can handle cloning despite this directory being around.
+ */
+ git_futils_mkdir_r(LIVE_REPO_AS_DIR, 0777);
+#endif
}
void test_online_clone__cleanup(void)
@@ -116,6 +138,10 @@ void test_online_clone__cleanup(void)
cl_fixture_cleanup("./initial");
cl_fixture_cleanup("./subsequent");
+#if !defined(GIT_WIN32)
+ cl_fixture_cleanup("http:");
+#endif
+
git__free(_remote_url);
git__free(_remote_user);
git__free(_remote_pass);
@@ -149,6 +175,11 @@ void test_online_clone__cleanup(void)
git__free(_orig_https_proxy);
git__free(_orig_no_proxy);
+ cl_setenv("GIT_SSH", _orig_ssh_cmd);
+ git__free(_orig_ssh_cmd);
+
+ git__free(_ssh_cmd);
+
git_libgit2_opts(GIT_OPT_SET_SSL_CERT_LOCATIONS, NULL, NULL);
git_libgit2_opts(GIT_OPT_SET_SERVER_TIMEOUT, 0);
git_libgit2_opts(GIT_OPT_SET_SERVER_CONNECT_TIMEOUT, 0);
@@ -653,7 +684,7 @@ void test_online_clone__ssh_auth_methods(void)
{
int with_user;
-#ifndef GIT_SSH
+#ifndef GIT_SSH_LIBSSH2
clar__skip();
#endif
g_options.fetch_opts.callbacks.credentials = check_ssh_auth_methods;
@@ -675,7 +706,7 @@ void test_online_clone__ssh_auth_methods(void)
*/
void test_online_clone__ssh_certcheck_accepts_unknown(void)
{
-#if !defined(GIT_SSH) || !defined(GIT_SSH_MEMORY_CREDENTIALS)
+#if !defined(GIT_SSH_LIBSSH2) || !defined(GIT_SSH_MEMORY_CREDENTIALS)
clar__skip();
#endif
@@ -793,9 +824,10 @@ static int cred_foo_bar(git_credential **cred, const char *url, const char *user
void test_online_clone__ssh_cannot_change_username(void)
{
-#ifndef GIT_SSH
+#ifndef GIT_SSH_LIBSSH2
clar__skip();
#endif
+
g_options.fetch_opts.callbacks.credentials = cred_foo_bar;
cl_git_fail(git_clone(&g_repo, "ssh://git@github.com/libgit2/TestGitRepository", "./foo", &g_options));
@@ -837,6 +869,10 @@ static int ssh_certificate_check(git_cert *cert, int valid, const char *host, vo
void test_online_clone__ssh_cert(void)
{
+#ifndef GIT_SSH_LIBSSH2
+ cl_skip();
+#endif
+
g_options.fetch_opts.callbacks.certificate_check = ssh_certificate_check;
if (!_remote_ssh_fingerprint)
@@ -908,12 +944,12 @@ void test_online_clone__certificate_invalid(void)
{
g_options.fetch_opts.callbacks.certificate_check = fail_certificate_check;
- cl_git_fail_with(git_clone(&g_repo, "https://github.com/libgit2/TestGitRepository", "./foo", &g_options),
- GIT_ECERTIFICATE);
+ cl_git_fail_with(GIT_ECERTIFICATE,
+ git_clone(&g_repo, "https://github.com/libgit2/TestGitRepository", "./foo", &g_options));
-#ifdef GIT_SSH
- cl_git_fail_with(git_clone(&g_repo, "ssh://github.com/libgit2/TestGitRepository", "./foo", &g_options),
- GIT_ECERTIFICATE);
+#ifdef GIT_SSH_LIBSSH2
+ cl_git_fail_with(GIT_ECERTIFICATE,
+ git_clone(&g_repo, "ssh://github.com/libgit2/TestGitRepository", "./foo", &g_options));
#endif
}
diff --git a/tests/libgit2/online/fetch.c b/tests/libgit2/online/fetch.c
index a557bbf..08a14c6 100644
--- a/tests/libgit2/online/fetch.c
+++ b/tests/libgit2/online/fetch.c
@@ -110,6 +110,26 @@ void test_online_fetch__fetch_twice(void)
git_remote_free(remote);
}
+void test_online_fetch__fetch_with_empty_http_proxy(void)
+{
+ git_remote *remote;
+ git_config *config;
+ git_fetch_options opts = GIT_FETCH_OPTIONS_INIT;
+
+ opts.proxy_opts.type = GIT_PROXY_AUTO;
+
+ cl_git_pass(git_repository_config(&config, _repo));
+ cl_git_pass(git_config_set_string(config, "http.proxy", ""));
+
+ cl_git_pass(git_remote_create(&remote, _repo, "test",
+ "https://github.com/libgit2/TestGitRepository"));
+ cl_git_pass(git_remote_fetch(remote, NULL, &opts, NULL));
+
+ git_remote_disconnect(remote);
+ git_remote_free(remote);
+ git_config_free(config);
+}
+
static int transferProgressCallback(const git_indexer_progress *stats, void *payload)
{
bool *invoked = (bool *)payload;
@@ -128,6 +148,8 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date
git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
opts.bare = true;
+ counter = 0;
+
cl_git_pass(git_clone(&_repository, "https://github.com/libgit2/TestGitRepository.git",
"./fetch/lg2", &opts));
git_repository_free(_repository);
@@ -141,11 +163,52 @@ void test_online_fetch__doesnt_retrieve_a_pack_when_the_repository_is_up_to_date
options.callbacks.transfer_progress = &transferProgressCallback;
options.callbacks.payload = &invoked;
+ options.callbacks.update_tips = update_tips;
cl_git_pass(git_remote_download(remote, NULL, &options));
cl_assert_equal_i(false, invoked);
- cl_git_pass(git_remote_update_tips(remote, &options.callbacks, 1, options.download_tags, NULL));
+ cl_git_pass(git_remote_update_tips(remote, &options.callbacks, GIT_REMOTE_UPDATE_FETCHHEAD, options.download_tags, NULL));
+ cl_assert_equal_i(0, counter);
+
+ git_remote_disconnect(remote);
+
+ git_remote_free(remote);
+ git_repository_free(_repository);
+}
+
+void test_online_fetch__report_unchanged_tips(void)
+{
+ git_repository *_repository;
+ bool invoked = false;
+ git_remote *remote;
+ git_fetch_options options = GIT_FETCH_OPTIONS_INIT;
+ git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
+ opts.bare = true;
+
+ counter = 0;
+
+ cl_git_pass(git_clone(&_repository, "https://github.com/libgit2/TestGitRepository.git",
+ "./fetch/lg2", &opts));
+ git_repository_free(_repository);
+
+ cl_git_pass(git_repository_open(&_repository, "./fetch/lg2"));
+
+ cl_git_pass(git_remote_lookup(&remote, _repository, "origin"));
+ cl_git_pass(git_remote_connect(remote, GIT_DIRECTION_FETCH, NULL, NULL, NULL));
+
+ cl_assert_equal_i(false, invoked);
+
+ options.callbacks.transfer_progress = &transferProgressCallback;
+ options.callbacks.payload = &invoked;
+ options.callbacks.update_tips = update_tips;
+ cl_git_pass(git_remote_download(remote, NULL, &options));
+
+ cl_assert_equal_i(false, invoked);
+
+ cl_git_pass(git_remote_update_tips(remote, &options.callbacks, GIT_REMOTE_UPDATE_REPORT_UNCHANGED, options.download_tags, NULL));
+ cl_assert(counter > 0);
+
git_remote_disconnect(remote);
git_remote_free(remote);
diff --git a/tests/libgit2/online/push.c b/tests/libgit2/online/push.c
index 204572c..e5693bf 100644
--- a/tests/libgit2/online/push.c
+++ b/tests/libgit2/online/push.c
@@ -5,6 +5,7 @@
#include "push_util.h"
#include "refspec.h"
#include "remote.h"
+#include "futils.h"
static git_repository *_repo;
@@ -20,7 +21,12 @@ static char *_remote_ssh_passphrase = NULL;
static char *_remote_default = NULL;
static char *_remote_expectcontinue = NULL;
-static int cred_acquire_cb(git_credential **, const char *, const char *, unsigned int, void *);
+static char *_remote_push_options = NULL;
+
+static char *_orig_ssh_cmd = NULL;
+static char *_ssh_cmd = NULL;
+
+static int cred_acquire_cb(git_credential **, const char *, const char *, unsigned int, void *);
static git_remote *_remote;
static record_callbacks_data _record_cbs_data = {{ 0 }};
@@ -367,8 +373,17 @@ void test_online_push__initialize(void)
_remote_ssh_passphrase = cl_getenv("GITTEST_REMOTE_SSH_PASSPHRASE");
_remote_default = cl_getenv("GITTEST_REMOTE_DEFAULT");
_remote_expectcontinue = cl_getenv("GITTEST_REMOTE_EXPECTCONTINUE");
+ _remote_push_options = cl_getenv("GITTEST_PUSH_OPTIONS");
_remote = NULL;
+ _orig_ssh_cmd = cl_getenv("GIT_SSH");
+ _ssh_cmd = cl_getenv("GITTEST_SSH_CMD");
+
+ if (_ssh_cmd)
+ cl_setenv("GIT_SSH", _ssh_cmd);
+ else
+ cl_setenv("GIT_SSH", NULL);
+
/* Skip the test if we're missing the remote URL */
if (!_remote_url)
cl_skip();
@@ -422,6 +437,10 @@ void test_online_push__cleanup(void)
git__free(_remote_ssh_passphrase);
git__free(_remote_default);
git__free(_remote_expectcontinue);
+ git__free(_remote_push_options);
+
+ git__free(_orig_ssh_cmd);
+ git__free(_ssh_cmd);
/* Freed by cl_git_sandbox_cleanup */
_repo = NULL;
@@ -430,6 +449,7 @@ void test_online_push__cleanup(void)
record_callbacks_data_clear(&_record_cbs_data);
+ cl_fixture_cleanup("push-options-result");
cl_fixture_cleanup("testrepo.git");
cl_git_sandbox_cleanup();
}
@@ -472,7 +492,8 @@ static void do_push(
const char *refspecs[], size_t refspecs_len,
push_status expected_statuses[], size_t expected_statuses_len,
expected_ref expected_refs[], size_t expected_refs_len,
- int expected_ret, int check_progress_cb, int check_update_tips_cb)
+ int expected_ret, int check_progress_cb, int check_update_tips_cb,
+ git_strarray *remote_push_options)
{
git_push_options opts = GIT_PUSH_OPTIONS_INIT;
size_t i;
@@ -484,6 +505,9 @@ static void do_push(
/* Auto-detect the number of threads to use */
opts.pb_parallelism = 0;
+ if (remote_push_options)
+ memcpy(&opts.remote_push_options, remote_push_options, sizeof(git_strarray));
+
memcpy(&opts.callbacks, &_record_cbs, sizeof(git_remote_callbacks));
data = opts.callbacks.payload;
@@ -527,13 +551,12 @@ static void do_push(
verify_update_tips_callback(_remote, expected_refs, expected_refs_len);
}
-
}
/* Call push_finish() without ever calling git_push_add_refspec() */
void test_online_push__noop(void)
{
- do_push(NULL, 0, NULL, 0, NULL, 0, 0, 0, 1);
+ do_push(NULL, 0, NULL, 0, NULL, 0, 0, 0, 1, NULL);
}
void test_online_push__b1(void)
@@ -543,7 +566,9 @@ void test_online_push__b1(void)
expected_ref exp_refs[] = { { "refs/heads/b1", &_oid_b1 } };
do_push(specs, ARRAY_SIZE(specs),
exp_stats, ARRAY_SIZE(exp_stats),
- exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1);
+ exp_refs, ARRAY_SIZE(exp_refs),
+ 0, 1, 1,
+ NULL);
}
void test_online_push__b2(void)
@@ -553,7 +578,9 @@ void test_online_push__b2(void)
expected_ref exp_refs[] = { { "refs/heads/b2", &_oid_b2 } };
do_push(specs, ARRAY_SIZE(specs),
exp_stats, ARRAY_SIZE(exp_stats),
- exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1);
+ exp_refs, ARRAY_SIZE(exp_refs),
+ 0, 1, 1,
+ NULL);
}
void test_online_push__b3(void)
@@ -563,7 +590,9 @@ void test_online_push__b3(void)
expected_ref exp_refs[] = { { "refs/heads/b3", &_oid_b3 } };
do_push(specs, ARRAY_SIZE(specs),
exp_stats, ARRAY_SIZE(exp_stats),
- exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1);
+ exp_refs, ARRAY_SIZE(exp_refs),
+ 0, 1, 1,
+ NULL);
}
void test_online_push__b4(void)
@@ -573,7 +602,9 @@ void test_online_push__b4(void)
expected_ref exp_refs[] = { { "refs/heads/b4", &_oid_b4 } };
do_push(specs, ARRAY_SIZE(specs),
exp_stats, ARRAY_SIZE(exp_stats),
- exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1);
+ exp_refs, ARRAY_SIZE(exp_refs),
+ 0, 1, 1,
+ NULL);
}
void test_online_push__b5(void)
@@ -583,13 +614,15 @@ void test_online_push__b5(void)
expected_ref exp_refs[] = { { "refs/heads/b5", &_oid_b5 } };
do_push(specs, ARRAY_SIZE(specs),
exp_stats, ARRAY_SIZE(exp_stats),
- exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1);
+ exp_refs, ARRAY_SIZE(exp_refs),
+ 0, 1, 1,
+ NULL);
}
void test_online_push__b5_cancel(void)
{
const char *specs[] = { "refs/heads/b5:refs/heads/b5" };
- do_push(specs, ARRAY_SIZE(specs), NULL, 0, NULL, 0, GIT_EUSER, 1, 1);
+ do_push(specs, ARRAY_SIZE(specs), NULL, 0, NULL, 0, GIT_EUSER, 1, 1, NULL);
}
void test_online_push__multi(void)
@@ -620,7 +653,9 @@ void test_online_push__multi(void)
};
do_push(specs, ARRAY_SIZE(specs),
exp_stats, ARRAY_SIZE(exp_stats),
- exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1);
+ exp_refs, ARRAY_SIZE(exp_refs),
+ 0, 1, 1,
+ NULL);
cl_git_pass(git_reflog_read(&log, _repo, "refs/remotes/test/b1"));
entry = git_reflog_entry_byindex(log, 0);
@@ -641,16 +676,21 @@ void test_online_push__implicit_tgt(void)
const char *specs2[] = { "refs/heads/b2" };
push_status exp_stats2[] = { { "refs/heads/b2", 1 } };
expected_ref exp_refs2[] = {
- { "refs/heads/b1", &_oid_b1 },
- { "refs/heads/b2", &_oid_b2 }
+ { "refs/heads/b1", &_oid_b1 },
+ { "refs/heads/b2", &_oid_b2 }
};
do_push(specs1, ARRAY_SIZE(specs1),
exp_stats1, ARRAY_SIZE(exp_stats1),
- exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1, 1);
+ exp_refs1, ARRAY_SIZE(exp_refs1),
+ 0, 1, 1,
+ NULL);
+
do_push(specs2, ARRAY_SIZE(specs2),
exp_stats2, ARRAY_SIZE(exp_stats2),
- exp_refs2, ARRAY_SIZE(exp_refs2), 0, 0, 0);
+ exp_refs2, ARRAY_SIZE(exp_refs2),
+ 0, 0, 0,
+ NULL);
}
void test_online_push__fast_fwd(void)
@@ -672,19 +712,27 @@ void test_online_push__fast_fwd(void)
do_push(specs_init, ARRAY_SIZE(specs_init),
exp_stats_init, ARRAY_SIZE(exp_stats_init),
- exp_refs_init, ARRAY_SIZE(exp_refs_init), 0, 1, 1);
+ exp_refs_init, ARRAY_SIZE(exp_refs_init),
+ 0, 1, 1,
+ NULL);
do_push(specs_ff, ARRAY_SIZE(specs_ff),
exp_stats_ff, ARRAY_SIZE(exp_stats_ff),
- exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0, 0, 0);
+ exp_refs_ff, ARRAY_SIZE(exp_refs_ff),
+ 0, 0, 0,
+ NULL);
do_push(specs_reset, ARRAY_SIZE(specs_reset),
exp_stats_init, ARRAY_SIZE(exp_stats_init),
- exp_refs_init, ARRAY_SIZE(exp_refs_init), 0, 0, 0);
+ exp_refs_init, ARRAY_SIZE(exp_refs_init),
+ 0, 0, 0,
+ NULL);
do_push(specs_ff_force, ARRAY_SIZE(specs_ff_force),
exp_stats_ff, ARRAY_SIZE(exp_stats_ff),
- exp_refs_ff, ARRAY_SIZE(exp_refs_ff), 0, 0, 0);
+ exp_refs_ff, ARRAY_SIZE(exp_refs_ff),
+ 0, 0, 0,
+ NULL);
}
void test_online_push__tag_commit(void)
@@ -694,7 +742,9 @@ void test_online_push__tag_commit(void)
expected_ref exp_refs[] = { { "refs/tags/tag-commit", &_tag_commit } };
do_push(specs, ARRAY_SIZE(specs),
exp_stats, ARRAY_SIZE(exp_stats),
- exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1);
+ exp_refs, ARRAY_SIZE(exp_refs),
+ 0, 1, 1,
+ NULL);
}
void test_online_push__tag_tree(void)
@@ -704,7 +754,9 @@ void test_online_push__tag_tree(void)
expected_ref exp_refs[] = { { "refs/tags/tag-tree", &_tag_tree } };
do_push(specs, ARRAY_SIZE(specs),
exp_stats, ARRAY_SIZE(exp_stats),
- exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1);
+ exp_refs, ARRAY_SIZE(exp_refs),
+ 0, 1, 1,
+ NULL);
}
void test_online_push__tag_blob(void)
@@ -714,7 +766,9 @@ void test_online_push__tag_blob(void)
expected_ref exp_refs[] = { { "refs/tags/tag-blob", &_tag_blob } };
do_push(specs, ARRAY_SIZE(specs),
exp_stats, ARRAY_SIZE(exp_stats),
- exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1);
+ exp_refs, ARRAY_SIZE(exp_refs),
+ 0, 1, 1,
+ NULL);
}
void test_online_push__tag_lightweight(void)
@@ -724,7 +778,9 @@ void test_online_push__tag_lightweight(void)
expected_ref exp_refs[] = { { "refs/tags/tag-lightweight", &_tag_lightweight } };
do_push(specs, ARRAY_SIZE(specs),
exp_stats, ARRAY_SIZE(exp_stats),
- exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1);
+ exp_refs, ARRAY_SIZE(exp_refs),
+ 0, 1, 1,
+ NULL);
}
void test_online_push__tag_to_tag(void)
@@ -734,7 +790,9 @@ void test_online_push__tag_to_tag(void)
expected_ref exp_refs[] = { { "refs/tags/tag-tag", &_tag_tag } };
do_push(specs, ARRAY_SIZE(specs),
exp_stats, ARRAY_SIZE(exp_stats),
- exp_refs, ARRAY_SIZE(exp_refs), 0, 0, 0);
+ exp_refs, ARRAY_SIZE(exp_refs),
+ 0, 0, 0,
+ NULL);
}
void test_online_push__force(void)
@@ -751,17 +809,80 @@ void test_online_push__force(void)
do_push(specs1, ARRAY_SIZE(specs1),
exp_stats1, ARRAY_SIZE(exp_stats1),
- exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1, 1);
+ exp_refs1, ARRAY_SIZE(exp_refs1),
+ 0, 1, 1,
+ NULL);
do_push(specs2, ARRAY_SIZE(specs2),
NULL, 0,
- exp_refs1, ARRAY_SIZE(exp_refs1), GIT_ENONFASTFORWARD, 0, 0);
+ exp_refs1, ARRAY_SIZE(exp_refs1),
+ GIT_ENONFASTFORWARD, 0, 0,
+ NULL);
/* Non-fast-forward update with force should pass. */
record_callbacks_data_clear(&_record_cbs_data);
do_push(specs2_force, ARRAY_SIZE(specs2_force),
exp_stats2_force, ARRAY_SIZE(exp_stats2_force),
- exp_refs2_force, ARRAY_SIZE(exp_refs2_force), 0, 1, 1);
+ exp_refs2_force, ARRAY_SIZE(exp_refs2_force),
+ 0, 1, 1,
+ NULL);
+}
+
+static void push_option_test(git_strarray given_options, const char *expected_option)
+{
+ const char *specs[] = { "refs/heads/b1:refs/heads/b1" };
+ push_status exp_stats[] = { { "refs/heads/b1", 1 } };
+ expected_ref exp_refs[] = { { "refs/heads/b1", &_oid_b1 } };
+ git_str push_options_path = GIT_STR_INIT;
+ git_str push_options_result = GIT_STR_INIT;
+ char *options[16];
+ git_strarray push_options = { options, given_options.count + 1 };
+ size_t i;
+
+ /* Skip the test if we're missing the push options result file */
+ if (!_remote_push_options)
+ cl_skip();
+
+ cl_assert(given_options.count < 16);
+
+ cl_git_pass(git_str_joinpath(&push_options_path, clar_sandbox_path(), "push-options-result"));
+
+ options[0] = push_options_path.ptr;
+ for (i = 0; i < given_options.count; i++)
+ options[i + 1] = given_options.strings[i];
+
+ do_push(specs, ARRAY_SIZE(specs),
+ exp_stats, ARRAY_SIZE(exp_stats),
+ exp_refs, ARRAY_SIZE(exp_refs),
+ 0, 1, 1,
+ &push_options);
+
+ cl_assert(git_fs_path_exists(push_options_path.ptr));
+ cl_git_pass(git_futils_readbuffer(&push_options_result, push_options_path.ptr));
+
+ cl_assert_equal_s(expected_option, git_str_cstr(&push_options_result));
+ git_str_dispose(&push_options_result);
+ git_str_dispose(&push_options_path);
+}
+
+void test_online_push__options(void)
+{
+ char *push_options_string_args_test_1[1] = { "test_string" };
+ git_strarray push_options_test_1 = { push_options_string_args_test_1, 1 };
+
+ char *push_options_string_args_test_2[2] = { "test_string", "another arg?" };
+ git_strarray push_options_test_2 = { push_options_string_args_test_2, 2 };
+
+ char *push_options_string_args_test_3[1] = { "👨ðŸ¿â€ðŸ’» but can it do unicode? 🇺🇦" };
+ git_strarray push_options_test_3 = { push_options_string_args_test_3, 1 };
+
+ char *push_options_string_args_test_4[3] = { "\0", "\0", "\0" };
+ git_strarray push_options_test_4 = { push_options_string_args_test_4, 3 };
+
+ push_option_test(push_options_test_1, "test_string");
+ push_option_test(push_options_test_2, "test_stringanother arg?");
+ push_option_test(push_options_test_3, "👨ðŸ¿â€ðŸ’» but can it do unicode? 🇺🇦");
+ push_option_test(push_options_test_4, "\0\0\0");
}
void test_online_push__delete(void)
@@ -792,7 +913,9 @@ void test_online_push__delete(void)
do_push(specs1, ARRAY_SIZE(specs1),
exp_stats1, ARRAY_SIZE(exp_stats1),
- exp_refs1, ARRAY_SIZE(exp_refs1), 0, 1, 1);
+ exp_refs1, ARRAY_SIZE(exp_refs1),
+ 0, 1, 1,
+ NULL);
/* When deleting a non-existent branch, the git client sends zero for both
* the old and new commit id. This should succeed on the server with the
@@ -802,23 +925,35 @@ void test_online_push__delete(void)
*/
do_push(specs_del_fake, ARRAY_SIZE(specs_del_fake),
exp_stats_fake, 1,
- exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0, 0);
+ exp_refs1, ARRAY_SIZE(exp_refs1),
+ 0, 0, 0,
+ NULL);
+
do_push(specs_del_fake_force, ARRAY_SIZE(specs_del_fake_force),
exp_stats_fake, 1,
- exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0, 0);
+ exp_refs1, ARRAY_SIZE(exp_refs1),
+ 0, 0, 0,
+ NULL);
/* Delete one of the pushed branches. */
do_push(specs_delete, ARRAY_SIZE(specs_delete),
exp_stats_delete, ARRAY_SIZE(exp_stats_delete),
- exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0, 0, 0);
+ exp_refs_delete, ARRAY_SIZE(exp_refs_delete),
+ 0, 0, 0,
+ NULL);
/* Re-push branches and retry delete with force. */
do_push(specs1, ARRAY_SIZE(specs1),
exp_stats1, ARRAY_SIZE(exp_stats1),
- exp_refs1, ARRAY_SIZE(exp_refs1), 0, 0, 0);
+ exp_refs1, ARRAY_SIZE(exp_refs1),
+ 0, 0, 0,
+ NULL);
+
do_push(specs_delete_force, ARRAY_SIZE(specs_delete_force),
exp_stats_delete, ARRAY_SIZE(exp_stats_delete),
- exp_refs_delete, ARRAY_SIZE(exp_refs_delete), 0, 0, 0);
+ exp_refs_delete, ARRAY_SIZE(exp_refs_delete),
+ 0, 0, 0,
+ NULL);
}
void test_online_push__bad_refspecs(void)
@@ -862,7 +997,9 @@ void test_online_push__expressions(void)
do_push(specs_left_expr, ARRAY_SIZE(specs_left_expr),
exp_stats, ARRAY_SIZE(exp_stats),
- exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1);
+ exp_refs, ARRAY_SIZE(exp_refs),
+ 0, 1, 1,
+ NULL);
}
void test_online_push__notes(void)
@@ -884,13 +1021,17 @@ void test_online_push__notes(void)
do_push(specs, ARRAY_SIZE(specs),
exp_stats, ARRAY_SIZE(exp_stats),
- exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1);
+ exp_refs, ARRAY_SIZE(exp_refs),
+ 0, 1, 1,
+ NULL);
/* And make sure to delete the note */
do_push(specs_del, ARRAY_SIZE(specs_del),
exp_stats, 1,
- NULL, 0, 0, 0, 0);
+ NULL, 0,
+ 0, 0, 0,
+ NULL);
git_signature_free(signature);
}
@@ -920,13 +1061,17 @@ void test_online_push__configured(void)
do_push(NULL, 0,
exp_stats, ARRAY_SIZE(exp_stats),
- exp_refs, ARRAY_SIZE(exp_refs), 0, 1, 1);
+ exp_refs, ARRAY_SIZE(exp_refs),
+ 0, 1, 1,
+ NULL);
/* And make sure to delete the note */
do_push(specs_del, ARRAY_SIZE(specs_del),
exp_stats, 1,
- NULL, 0, 0, 0, 0);
+ NULL, 0,
+ 0, 0, 0,
+ NULL);
git_signature_free(signature);
}
diff --git a/tests/libgit2/online/shallow.c b/tests/libgit2/online/shallow.c
index 5c0e656..ee4aaf3 100644
--- a/tests/libgit2/online/shallow.c
+++ b/tests/libgit2/online/shallow.c
@@ -164,3 +164,102 @@ void test_online_shallow__unshallow(void)
git_revwalk_free(walk);
git_repository_free(repo);
}
+
+void test_online_shallow__deepen_six(void)
+{
+ git_str path = GIT_STR_INIT;
+ git_repository *repo;
+ git_revwalk *walk;
+ git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
+ git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT;
+ git_remote *origin = NULL;
+ git_oid oid;
+ git_oid *roots;
+ size_t roots_len;
+ size_t num_commits = 0;
+ int error = 0;
+
+ clone_opts.fetch_opts.depth = 5;
+ clone_opts.remote_cb = remote_single_branch;
+
+ git_str_joinpath(&path, clar_sandbox_path(), "deepen_6");
+ cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_str_cstr(&path), &clone_opts));
+ cl_assert_equal_b(true, git_repository_is_shallow(repo));
+
+ fetch_opts.depth = 6;
+ cl_git_pass(git_remote_lookup(&origin, repo, "origin"));
+ cl_git_pass(git_remote_fetch(origin, NULL, &fetch_opts, NULL));
+ cl_assert_equal_b(true, git_repository_is_shallow(repo));
+
+ cl_git_pass(git_repository__shallow_roots(&roots, &roots_len, repo));
+ cl_assert_equal_i(4, roots_len);
+ cl_assert_equal_s("58be4659bb571194ed4562d04b359d26216f526e", git_oid_tostr_s(&roots[0]));
+ cl_assert_equal_s("d31f5a60d406e831d056b8ac2538d515100c2df2", git_oid_tostr_s(&roots[1]));
+ cl_assert_equal_s("6462e7d8024396b14d7651e2ec11e2bbf07a05c4", git_oid_tostr_s(&roots[2]));
+ cl_assert_equal_s("2c349335b7f797072cf729c4f3bb0914ecb6dec9", git_oid_tostr_s(&roots[3]));
+
+ git_revwalk_new(&walk, repo);
+ git_revwalk_push_head(walk);
+
+ while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) {
+ num_commits++;
+ }
+
+ cl_assert_equal_i(num_commits, 17);
+ cl_assert_equal_i(error, GIT_ITEROVER);
+
+ git__free(roots);
+ git_remote_free(origin);
+ git_str_dispose(&path);
+ git_revwalk_free(walk);
+ git_repository_free(repo);
+}
+
+void test_online_shallow__shorten_four(void)
+{
+ git_str path = GIT_STR_INIT;
+ git_repository *repo;
+ git_revwalk *walk;
+ git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
+ git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT;
+ git_remote *origin = NULL;
+ git_oid oid;
+ git_oid *roots;
+ size_t roots_len;
+ size_t num_commits = 0;
+ int error = 0;
+
+ clone_opts.fetch_opts.depth = 5;
+ clone_opts.remote_cb = remote_single_branch;
+
+ git_str_joinpath(&path, clar_sandbox_path(), "shorten_4");
+ cl_git_pass(git_clone(&repo, "https://github.com/libgit2/TestGitRepository", git_str_cstr(&path), &clone_opts));
+ cl_assert_equal_b(true, git_repository_is_shallow(repo));
+
+ fetch_opts.depth = 4;
+ cl_git_pass(git_remote_lookup(&origin, repo, "origin"));
+ cl_git_pass(git_remote_fetch(origin, NULL, &fetch_opts, NULL));
+ cl_assert_equal_b(true, git_repository_is_shallow(repo));
+
+ cl_git_pass(git_repository__shallow_roots(&roots, &roots_len, repo));
+ cl_assert_equal_i(3, roots_len);
+ cl_assert_equal_s("d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864", git_oid_tostr_s(&roots[0]));
+ cl_assert_equal_s("59706a11bde2b9899a278838ef20a97e8f8795d2", git_oid_tostr_s(&roots[1]));
+ cl_assert_equal_s("bab66b48f836ed950c99134ef666436fb07a09a0", git_oid_tostr_s(&roots[2]));
+
+ git_revwalk_new(&walk, repo);
+ git_revwalk_push_head(walk);
+
+ while ((error = git_revwalk_next(&oid, walk)) == GIT_OK) {
+ num_commits++;
+ }
+
+ cl_assert_equal_i(num_commits, 10);
+ cl_assert_equal_i(error, GIT_ITEROVER);
+
+ git__free(roots);
+ git_remote_free(origin);
+ git_str_dispose(&path);
+ git_revwalk_free(walk);
+ git_repository_free(repo);
+}
diff --git a/tests/libgit2/pack/packbuilder.c b/tests/libgit2/pack/packbuilder.c
index ff3dc1f..7da3877 100644
--- a/tests/libgit2/pack/packbuilder.c
+++ b/tests/libgit2/pack/packbuilder.c
@@ -98,9 +98,6 @@ void test_pack_packbuilder__create_pack(void)
{
git_indexer_progress stats;
git_str buf = GIT_STR_INIT, path = GIT_STR_INIT;
- git_hash_ctx ctx;
- unsigned char hash[GIT_HASH_SHA1_SIZE];
- char hex[(GIT_HASH_SHA1_SIZE * 2) + 1];
seed_packbuilder();
@@ -114,33 +111,13 @@ void test_pack_packbuilder__create_pack(void)
cl_git_pass(git_indexer_commit(_indexer, &stats));
git_str_printf(&path, "pack-%s.pack", git_indexer_name(_indexer));
-
- /*
- * By default, packfiles are created with only one thread.
- * Therefore we can predict the object ordering and make sure
- * we create exactly the same pack as git.git does when *not*
- * reusing existing deltas (as libgit2).
- *
- * $ cd tests/resources/testrepo.git
- * $ git rev-list --objects HEAD | \
- * git pack-objects -q --no-reuse-delta --threads=1 pack
- * $ sha1sum pack-7f5fa362c664d68ba7221259be1cbd187434b2f0.pack
- * 5d410bdf97cf896f9007681b92868471d636954b
- *
- */
+ cl_assert(git_fs_path_exists(path.ptr));
cl_git_pass(git_futils_readbuffer(&buf, git_str_cstr(&path)));
-
- cl_git_pass(git_hash_ctx_init(&ctx, GIT_HASH_ALGORITHM_SHA1));
- cl_git_pass(git_hash_update(&ctx, buf.ptr, buf.size));
- cl_git_pass(git_hash_final(hash, &ctx));
- git_hash_ctx_cleanup(&ctx);
+ cl_assert(buf.size > 256);
git_str_dispose(&path);
git_str_dispose(&buf);
-
- git_hash_fmt(hex, hash, GIT_HASH_SHA1_SIZE);
- cl_assert_equal_s(hex, "5d410bdf97cf896f9007681b92868471d636954b");
}
void test_pack_packbuilder__get_name(void)
@@ -148,22 +125,49 @@ void test_pack_packbuilder__get_name(void)
seed_packbuilder();
cl_git_pass(git_packbuilder_write(_packbuilder, ".", 0, NULL, NULL));
- cl_assert_equal_s("7f5fa362c664d68ba7221259be1cbd187434b2f0", git_packbuilder_name(_packbuilder));
+ cl_assert(git_packbuilder_name(_packbuilder) != NULL);
+}
+
+static void get_packfile_path(git_str *out, git_packbuilder *pb)
+{
+ git_str_puts(out, "pack-");
+ git_str_puts(out, git_packbuilder_name(pb));
+ git_str_puts(out, ".pack");
+}
+
+static void get_index_path(git_str *out, git_packbuilder *pb)
+{
+ git_str_puts(out, "pack-");
+ git_str_puts(out, git_packbuilder_name(pb));
+ git_str_puts(out, ".idx");
}
void test_pack_packbuilder__write_default_path(void)
{
+ git_str idx = GIT_STR_INIT, pack = GIT_STR_INIT;
+
seed_packbuilder();
cl_git_pass(git_packbuilder_write(_packbuilder, NULL, 0, NULL, NULL));
- cl_assert(git_fs_path_exists("objects/pack/pack-7f5fa362c664d68ba7221259be1cbd187434b2f0.idx"));
- cl_assert(git_fs_path_exists("objects/pack/pack-7f5fa362c664d68ba7221259be1cbd187434b2f0.pack"));
+
+ git_str_puts(&idx, "objects/pack/");
+ get_index_path(&idx, _packbuilder);
+
+ git_str_puts(&pack, "objects/pack/");
+ get_packfile_path(&pack, _packbuilder);
+
+ cl_assert(git_fs_path_exists(idx.ptr));
+ cl_assert(git_fs_path_exists(pack.ptr));
+
+ git_str_dispose(&idx);
+ git_str_dispose(&pack);
}
static void test_write_pack_permission(mode_t given, mode_t expected)
{
struct stat statbuf;
mode_t mask, os_mask;
+ git_str idx = GIT_STR_INIT, pack = GIT_STR_INIT;
seed_packbuilder();
@@ -181,11 +185,17 @@ static void test_write_pack_permission(mode_t given, mode_t expected)
mask = p_umask(0);
p_umask(mask);
- cl_git_pass(p_stat("pack-7f5fa362c664d68ba7221259be1cbd187434b2f0.idx", &statbuf));
+ get_index_path(&idx, _packbuilder);
+ get_packfile_path(&pack, _packbuilder);
+
+ cl_git_pass(p_stat(idx.ptr, &statbuf));
cl_assert_equal_i(statbuf.st_mode & os_mask, (expected & ~mask) & os_mask);
- cl_git_pass(p_stat("pack-7f5fa362c664d68ba7221259be1cbd187434b2f0.pack", &statbuf));
+ cl_git_pass(p_stat(pack.ptr, &statbuf));
cl_assert_equal_i(statbuf.st_mode & os_mask, (expected & ~mask) & os_mask);
+
+ git_str_dispose(&idx);
+ git_str_dispose(&pack);
}
void test_pack_packbuilder__permissions_standard(void)
diff --git a/tests/libgit2/rebase/sign.c b/tests/libgit2/rebase/sign.c
index 69bb1c6..45bac29 100644
--- a/tests/libgit2/rebase/sign.c
+++ b/tests/libgit2/rebase/sign.c
@@ -26,7 +26,7 @@ static int create_cb_passthrough(
const char *message,
const git_tree *tree,
size_t parent_count,
- const git_commit *parents[],
+ git_commit * const parents[],
void *payload)
{
GIT_UNUSED(out);
@@ -94,7 +94,7 @@ static int create_cb_signed_gpg(
const char *message,
const git_tree *tree,
size_t parent_count,
- const git_commit *parents[],
+ git_commit * const parents[],
void *payload)
{
git_buf commit_content = GIT_BUF_INIT;
@@ -202,7 +202,7 @@ static int create_cb_error(
const char *message,
const git_tree *tree,
size_t parent_count,
- const git_commit *parents[],
+ git_commit * const parents[],
void *payload)
{
GIT_UNUSED(out);
diff --git a/tests/libgit2/refs/branches/delete.c b/tests/libgit2/refs/branches/delete.c
index 6b3d507..63f8c5d 100644
--- a/tests/libgit2/refs/branches/delete.c
+++ b/tests/libgit2/refs/branches/delete.c
@@ -92,6 +92,21 @@ void test_refs_branches_delete__can_delete_a_local_branch(void)
git_reference_free(branch);
}
+void test_refs_branches_delete__can_delete_a_local_branch_with_multivar(void)
+{
+ git_reference *branch;
+ git_config *cfg;
+
+ cl_git_pass(git_repository_config(&cfg, repo));
+ cl_git_pass(git_config_set_multivar(
+ cfg, "branch.br2.gitpublishto", "^$", "example1@example.com"));
+ cl_git_pass(git_config_set_multivar(
+ cfg, "branch.br2.gitpublishto", "^$", "example2@example.com"));
+ cl_git_pass(git_branch_lookup(&branch, repo, "br2", GIT_BRANCH_LOCAL));
+ cl_git_pass(git_branch_delete(branch));
+ git_reference_free(branch);
+}
+
void test_refs_branches_delete__can_delete_a_remote_branch(void)
{
git_reference *branch;
diff --git a/tests/libgit2/refs/reflog/messages.c b/tests/libgit2/refs/reflog/messages.c
index 647c00d..4a2ecb0 100644
--- a/tests/libgit2/refs/reflog/messages.c
+++ b/tests/libgit2/refs/reflog/messages.c
@@ -233,7 +233,7 @@ void test_refs_reflog_messages__show_merge_for_merge_commits(void)
cl_git_pass(git_commit_create(&merge_commit_oid,
g_repo, "HEAD", s, s, NULL,
"Merge commit", tree,
- 2, (const struct git_commit **) parent_commits));
+ 2, parent_commits));
cl_reflog_check_entry(g_repo, GIT_HEAD_FILE, 0,
NULL,
diff --git a/tests/libgit2/refs/revparse.c b/tests/libgit2/refs/revparse.c
index d2f4648..9bc3bd1 100644
--- a/tests/libgit2/refs/revparse.c
+++ b/tests/libgit2/refs/revparse.c
@@ -747,6 +747,25 @@ void test_refs_revparse__try_to_retrieve_branch_before_abbrev_sha(void)
cl_git_sandbox_cleanup();
}
+void test_refs_revparse__at_at_end_of_refname(void)
+{
+ git_repository *repo;
+ git_reference *branch;
+ git_object *target;
+
+ repo = cl_git_sandbox_init("testrepo.git");
+
+ cl_git_pass(git_revparse_single(&target, repo, "HEAD"));
+ cl_git_pass(git_branch_create(&branch, repo, "master@", (git_commit *)target, 0));
+ git_object_free(target);
+
+ test_id_inrepo("master@", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750", NULL, GIT_REVSPEC_SINGLE, repo);
+
+ cl_git_fail_with(GIT_ENOTFOUND, git_revparse_single(&target, repo, "foo@"));
+
+ git_reference_free(branch);
+ cl_git_sandbox_cleanup();
+}
void test_refs_revparse__range(void)
{
diff --git a/tests/libgit2/remote/fetch.c b/tests/libgit2/remote/fetch.c
index 85e9920..a5d3272 100644
--- a/tests/libgit2/remote/fetch.c
+++ b/tests/libgit2/remote/fetch.c
@@ -75,6 +75,7 @@ static void do_time_travelling_fetch(git_oid *commit1id, git_oid *commit2id,
/* create two commits in repo 1 and a reference to them */
{
git_oid empty_tree_id;
+ git_commit *commit1;
git_tree *empty_tree;
git_signature *sig;
git_treebuilder *tb;
@@ -84,10 +85,12 @@ static void do_time_travelling_fetch(git_oid *commit1id, git_oid *commit2id,
cl_git_pass(git_signature_default(&sig, repo1));
cl_git_pass(git_commit_create(commit1id, repo1, REPO1_REFNAME, sig,
sig, NULL, "one", empty_tree, 0, NULL));
+ cl_git_pass(git_commit_lookup(&commit1, repo1, commit1id));
cl_git_pass(git_commit_create_v(commit2id, repo1, REPO1_REFNAME, sig,
- sig, NULL, "two", empty_tree, 1, commit1id));
+ sig, NULL, "two", empty_tree, 1, commit1));
git_tree_free(empty_tree);
+ git_commit_free(commit1);
git_signature_free(sig);
git_treebuilder_free(tb);
}
diff --git a/tests/libgit2/repo/getters.c b/tests/libgit2/repo/getters.c
index d401bb8..8e21d35 100644
--- a/tests/libgit2/repo/getters.c
+++ b/tests/libgit2/repo/getters.c
@@ -51,3 +51,63 @@ void test_repo_getters__retrieving_the_odb_honors_the_refcount(void)
git_odb_free(odb);
}
+
+void test_repo_getters__commit_parents(void)
+{
+ git_repository *repo;
+ git_commitarray parents;
+ git_oid first_parent;
+ git_oid merge_parents[4];
+
+ git_oid__fromstr(&first_parent, "099fabac3a9ea935598528c27f866e34089c2eff", GIT_OID_SHA1);
+
+ /* A commit on a new repository has no parents */
+
+ cl_git_pass(git_repository_init(&repo, "new_repo", false));
+ cl_git_pass(git_repository_commit_parents(&parents, repo));
+
+ cl_assert_equal_sz(0, parents.count);
+ cl_assert_equal_p(NULL, parents.commits);
+
+ git_commitarray_dispose(&parents);
+ git_repository_free(repo);
+
+ /* A standard commit has one parent */
+
+ repo = cl_git_sandbox_init("testrepo");
+ cl_git_pass(git_repository_commit_parents(&parents, repo));
+
+ cl_assert_equal_sz(1, parents.count);
+ cl_assert_equal_oid(&first_parent, git_commit_id(parents.commits[0]));
+
+ git_commitarray_dispose(&parents);
+
+ /* A merge commit has multiple parents */
+
+ cl_git_rewritefile("testrepo/.git/MERGE_HEAD",
+ "8496071c1b46c854b31185ea97743be6a8774479\n"
+ "5b5b025afb0b4c913b4c338a42934a3863bf3644\n"
+ "4a202b346bb0fb0db7eff3cffeb3c70babbd2045\n"
+ "9fd738e8f7967c078dceed8190330fc8648ee56a\n");
+
+ cl_git_pass(git_repository_commit_parents(&parents, repo));
+
+ cl_assert_equal_sz(5, parents.count);
+
+ cl_assert_equal_oid(&first_parent, git_commit_id(parents.commits[0]));
+
+ git_oid__fromstr(&merge_parents[0], "8496071c1b46c854b31185ea97743be6a8774479", GIT_OID_SHA1);
+ cl_assert_equal_oid(&merge_parents[0], git_commit_id(parents.commits[1]));
+ git_oid__fromstr(&merge_parents[1], "5b5b025afb0b4c913b4c338a42934a3863bf3644", GIT_OID_SHA1);
+ cl_assert_equal_oid(&merge_parents[1], git_commit_id(parents.commits[2]));
+ git_oid__fromstr(&merge_parents[2], "4a202b346bb0fb0db7eff3cffeb3c70babbd2045", GIT_OID_SHA1);
+ cl_assert_equal_oid(&merge_parents[2], git_commit_id(parents.commits[3]));
+ git_oid__fromstr(&merge_parents[3], "9fd738e8f7967c078dceed8190330fc8648ee56a", GIT_OID_SHA1);
+ cl_assert_equal_oid(&merge_parents[3], git_commit_id(parents.commits[4]));
+
+ git_commitarray_dispose(&parents);
+
+ git_repository_free(repo);
+
+ cl_fixture_cleanup("testrepo");
+}
diff --git a/tests/libgit2/repo/init.c b/tests/libgit2/repo/init.c
index d78ec06..446ab73 100644
--- a/tests/libgit2/repo/init.c
+++ b/tests/libgit2/repo/init.c
@@ -755,3 +755,28 @@ void test_repo_init__longpath(void)
git_str_dispose(&path);
#endif
}
+
+void test_repo_init__absolute_path_with_backslashes(void)
+{
+#ifdef GIT_WIN32
+ git_repository_init_options initopts = GIT_REPOSITORY_INIT_OPTIONS_INIT;
+ git_str path = GIT_STR_INIT;
+ char *c;
+
+ cl_set_cleanup(&cleanup_repository, "path");
+
+ cl_git_pass(git_str_joinpath(&path, clar_sandbox_path(), "path/to/newrepo"));
+
+ for (c = path.ptr; *c; c++) {
+ if (*c == '/')
+ *c = '\\';
+ }
+
+ initopts.flags |= GIT_REPOSITORY_INIT_MKDIR | GIT_REPOSITORY_INIT_MKPATH;
+
+ cl_git_pass(git_repository_init_ext(&g_repo, path.ptr, &initopts));
+ git_str_dispose(&path);
+#else
+ clar__skip();
+#endif
+}
diff --git a/tests/libgit2/repo/new.c b/tests/libgit2/repo/new.c
index d77e903..aaa917a 100644
--- a/tests/libgit2/repo/new.c
+++ b/tests/libgit2/repo/new.c
@@ -5,7 +5,11 @@ void test_repo_new__has_nothing(void)
{
git_repository *repo;
+#ifdef GIT_EXPERIMENTAL_SHA256
+ cl_git_pass(git_repository_new(&repo, GIT_OID_SHA1));
+#else
cl_git_pass(git_repository_new(&repo));
+#endif
cl_assert_equal_b(true, git_repository_is_bare(repo));
cl_assert_equal_p(NULL, git_repository_path(repo));
cl_assert_equal_p(NULL, git_repository_workdir(repo));
@@ -16,7 +20,11 @@ void test_repo_new__is_bare_until_workdir_set(void)
{
git_repository *repo;
+#ifdef GIT_EXPERIMENTAL_SHA256
+ cl_git_pass(git_repository_new(&repo, GIT_OID_SHA1));
+#else
cl_git_pass(git_repository_new(&repo));
+#endif
cl_assert_equal_b(true, git_repository_is_bare(repo));
cl_git_pass(git_repository_set_workdir(repo, clar_sandbox_path(), 0));
@@ -25,3 +33,30 @@ void test_repo_new__is_bare_until_workdir_set(void)
git_repository_free(repo);
}
+void test_repo_new__sha1(void)
+{
+ git_repository *repo;
+
+#ifdef GIT_EXPERIMENTAL_SHA256
+ cl_git_pass(git_repository_new(&repo, GIT_OID_SHA1));
+#else
+ cl_git_pass(git_repository_new(&repo));
+#endif
+ cl_assert_equal_i(GIT_OID_SHA1, git_repository_oid_type(repo));
+
+ git_repository_free(repo);
+}
+
+void test_repo_new__sha256(void)
+{
+#ifndef GIT_EXPERIMENTAL_SHA256
+ cl_skip();
+#else
+ git_repository *repo;
+
+ cl_git_pass(git_repository_new(&repo, GIT_OID_SHA256));
+ cl_assert_equal_i(GIT_OID_SHA256, git_repository_oid_type(repo));
+
+ git_repository_free(repo);
+#endif
+}
diff --git a/tests/libgit2/repo/open.c b/tests/libgit2/repo/open.c
index 3d1a062..d585513 100644
--- a/tests/libgit2/repo/open.c
+++ b/tests/libgit2/repo/open.c
@@ -316,7 +316,7 @@ static void unposix_path(git_str *path)
src = tgt = path->ptr;
/* convert "/d/..." to "d:\..." */
- if (src[0] == '/' && isalpha(src[1]) && src[2] == '/') {
+ if (src[0] == '/' && git__isalpha(src[1]) && src[2] == '/') {
*tgt++ = src[1];
*tgt++ = ':';
*tgt++ = '\\';
@@ -533,15 +533,21 @@ void test_repo_open__validates_bare_repo_ownership(void)
cl_git_fail_with(GIT_EOWNER, git_repository_open(&repo, "testrepo.git"));
}
-void test_repo_open__can_allowlist_dirs_with_problematic_ownership(void)
+static int test_safe_path(const char *path)
{
git_repository *repo;
git_str config_path = GIT_STR_INIT,
config_filename = GIT_STR_INIT,
config_data = GIT_STR_INIT;
+ int error;
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 1));
+ /*
+ * Sandbox the fixture, and ensure that when we fake an owner
+ * of "other" that the repository cannot be opened (and fails
+ * with `GIT_EOWNER`).
+ */
cl_fixture_sandbox("empty_standard_repo");
cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git"));
@@ -555,81 +561,179 @@ void test_repo_open__can_allowlist_dirs_with_problematic_ownership(void)
git_str_joinpath(&config_filename, config_path.ptr, ".gitconfig");
+ git_str_clear(&config_data);
git_str_printf(&config_data,
"[foo]\n" \
"\tbar = Foobar\n" \
"\tbaz = Baz!\n" \
"[safe]\n" \
- "\tdirectory = /non/existent/path\n" \
- "\tdirectory = /\n" \
- "\tdirectory = c:\\\\temp\n" \
- "\tdirectory = %s/%s\n" \
- "\tdirectory = /tmp\n" \
+ "\tdirectory = %s\n" \
"[bar]\n" \
"\tfoo = barfoo\n",
- clar_sandbox_path(), "empty_standard_repo");
+ path);
cl_git_rewritefile(config_filename.ptr, config_data.ptr);
- cl_git_pass(git_repository_open(&repo, "empty_standard_repo"));
+ error = git_repository_open(&repo, "empty_standard_repo");
git_repository_free(repo);
git_str_dispose(&config_path);
git_str_dispose(&config_filename);
git_str_dispose(&config_data);
+
+ return error;
}
-void test_repo_open__can_wildcard_allowlist_with_problematic_ownership(void)
+static int test_bare_safe_path(const char *path)
{
git_repository *repo;
- git_str config_path = GIT_STR_INIT, config_filename = GIT_STR_INIT;
+ git_str config_path = GIT_STR_INIT,
+ config_filename = GIT_STR_INIT,
+ config_data = GIT_STR_INIT;
+ int error;
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 1));
- cl_fixture_sandbox("empty_standard_repo");
- cl_git_pass(cl_rename(
- "empty_standard_repo/.gitted", "empty_standard_repo/.git"));
+ cl_fixture_sandbox("testrepo.git");
git_fs_path__set_owner(GIT_FS_PATH_OWNER_OTHER);
- cl_git_fail_with(
- GIT_EOWNER, git_repository_open(&repo, "empty_standard_repo"));
+ cl_git_fail_with(GIT_EOWNER, git_repository_open(&repo, "testrepo.git"));
/* Add safe.directory options to the global configuration */
git_str_joinpath(&config_path, clar_sandbox_path(), "__global_config");
cl_must_pass(p_mkdir(config_path.ptr, 0777));
- git_libgit2_opts(
- GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL,
- config_path.ptr);
+ git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, config_path.ptr);
git_str_joinpath(&config_filename, config_path.ptr, ".gitconfig");
- cl_git_rewritefile(config_filename.ptr, "[foo]\n"
- "\tbar = Foobar\n"
- "\tbaz = Baz!\n"
- "[safe]\n"
- "\tdirectory = *\n"
- "[bar]\n"
- "\tfoo = barfoo\n");
+ git_str_printf(&config_data,
+ "[foo]\n" \
+ "\tbar = Foobar\n" \
+ "\tbaz = Baz!\n" \
+ "[safe]\n" \
+ "\tdirectory = /non/existent/path\n" \
+ "\tdirectory = /\n" \
+ "\tdirectory = c:\\\\temp\n" \
+ "\tdirectory = %s\n" \
+ "\tdirectory = /tmp\n" \
+ "[bar]\n" \
+ "\tfoo = barfoo\n",
+ path);
+ cl_git_rewritefile(config_filename.ptr, config_data.ptr);
- cl_git_pass(git_repository_open(&repo, "empty_standard_repo"));
+ error = git_repository_open(&repo, "testrepo.git");
git_repository_free(repo);
git_str_dispose(&config_path);
git_str_dispose(&config_filename);
+ git_str_dispose(&config_data);
+
+ return error;
+}
+
+void test_repo_open__can_allowlist_dirs_with_problematic_ownership(void)
+{
+ git_str path = GIT_STR_INIT;
+
+ cl_git_pass(git_str_printf(&path, "%s/%s",
+ clar_sandbox_path(), "empty_standard_repo"));
+ cl_git_pass(test_safe_path(path.ptr));
+ git_str_dispose(&path);
+}
+
+void test_repo_open__safe_directory_fails_with_trailing_slash(void)
+{
+ git_str path = GIT_STR_INIT;
+
+ /*
+ * "/tmp/foo/" is not permitted; safe path must be specified
+ * as "/tmp/foo"
+ */
+ cl_git_pass(git_str_printf(&path, "%s/%s/",
+ clar_sandbox_path(), "empty_standard_repo"));
+ cl_git_fail_with(GIT_EOWNER, test_safe_path(path.ptr));
+ git_str_dispose(&path);
+}
+
+void test_repo_open__can_wildcard_allowlist_with_problematic_ownership(void)
+{
+ cl_git_pass(test_safe_path("*"));
}
void test_repo_open__can_allowlist_bare_gitdir(void)
{
+ git_str path = GIT_STR_INIT;
+
+ cl_git_pass(git_str_printf(&path, "%s/%s",
+ clar_sandbox_path(), "testrepo.git"));
+ cl_git_pass(test_bare_safe_path(path.ptr));
+ git_str_dispose(&path);
+}
+
+void test_repo_open__can_wildcard_allowlist_bare_gitdir(void)
+{
+ cl_git_pass(test_bare_safe_path("*"));
+}
+
+void test_repo_open__can_handle_prefixed_safe_paths(void)
+{
+#ifndef GIT_WIN32
+ git_str path = GIT_STR_INIT;
+
+ /*
+ * Using "%(prefix)/" becomes "%(prefix)//tmp/foo" - so
+ * "%(prefix)/" is stripped and means the literal path
+ * follows.
+ */
+ cl_git_pass(git_str_printf(&path, "%%(prefix)/%s/%s",
+ clar_sandbox_path(), "empty_standard_repo"));
+ cl_git_pass(test_safe_path(path.ptr));
+ git_str_dispose(&path);
+#endif
+}
+
+void test_repo_open__prefixed_safe_paths_must_have_two_slashes(void)
+{
+ git_str path = GIT_STR_INIT;
+
+ /*
+ * Using "%(prefix)" becomes "%(prefix)/tmp/foo" - so it's
+ * actually trying to look in the git prefix, for example,
+ * "/usr/local/tmp/foo", which we don't actually support.
+ */
+ cl_git_pass(git_str_printf(&path, "%%(prefix)%s/%s",
+ clar_sandbox_path(), "empty_standard_repo"));
+ cl_git_fail_with(GIT_EOWNER, test_safe_path(path.ptr));
+ git_str_dispose(&path);
+}
+
+void test_repo_open__can_handle_win32_prefixed_safe_paths(void)
+{
+#ifdef GIT_WIN32
git_repository *repo;
- git_str config_path = GIT_STR_INIT,
+ git_str unc_path = GIT_STR_INIT,
+ config_path = GIT_STR_INIT,
config_filename = GIT_STR_INIT,
config_data = GIT_STR_INIT;
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 1));
- cl_fixture_sandbox("testrepo.git");
+ cl_fixture_sandbox("empty_standard_repo");
+ cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git"));
+
+ /*
+ * On Windows, we can generally map a local drive to a UNC path;
+ * for example C:\Foo\Bar becomes //localhost/C$/Foo/bar
+ */
+ cl_git_pass(git_str_printf(&unc_path, "//localhost/%s/%s",
+ clar_sandbox_path(), "empty_standard_repo"));
+
+ if (unc_path.ptr[13] != ':' || unc_path.ptr[14] != '/')
+ cl_skip();
+
+ unc_path.ptr[13] = '$';
git_fs_path__set_owner(GIT_FS_PATH_OWNER_OTHER);
- cl_git_fail_with(GIT_EOWNER, git_repository_open(&repo, "testrepo.git"));
+ cl_git_fail_with(GIT_EOWNER, git_repository_open(&repo, unc_path.ptr));
/* Add safe.directory options to the global configuration */
git_str_joinpath(&config_path, clar_sandbox_path(), "__global_config");
@@ -638,64 +742,74 @@ void test_repo_open__can_allowlist_bare_gitdir(void)
git_str_joinpath(&config_filename, config_path.ptr, ".gitconfig");
+ /* The blank resets our sandbox directory and opening fails */
+
git_str_printf(&config_data,
- "[foo]\n" \
- "\tbar = Foobar\n" \
- "\tbaz = Baz!\n" \
- "[safe]\n" \
- "\tdirectory = /non/existent/path\n" \
- "\tdirectory = /\n" \
- "\tdirectory = c:\\\\temp\n" \
- "\tdirectory = %s/%s\n" \
- "\tdirectory = /tmp\n" \
- "[bar]\n" \
- "\tfoo = barfoo\n",
- clar_sandbox_path(), "testrepo.git");
+ "[safe]\n\tdirectory = %%(prefix)/%s\n",
+ unc_path.ptr);
cl_git_rewritefile(config_filename.ptr, config_data.ptr);
- cl_git_pass(git_repository_open(&repo, "testrepo.git"));
+ cl_git_pass(git_repository_open(&repo, unc_path.ptr));
git_repository_free(repo);
git_str_dispose(&config_path);
git_str_dispose(&config_filename);
git_str_dispose(&config_data);
+ git_str_dispose(&unc_path);
+#endif
}
-void test_repo_open__can_wildcard_allowlist_bare_gitdir(void)
+void test_repo_open__can_handle_win32_unc_safe_paths(void)
{
+#ifdef GIT_WIN32
git_repository *repo;
- git_str config_path = GIT_STR_INIT, config_filename = GIT_STR_INIT;
+ git_str unc_path = GIT_STR_INIT,
+ config_path = GIT_STR_INIT,
+ config_filename = GIT_STR_INIT,
+ config_data = GIT_STR_INIT;
cl_git_pass(git_libgit2_opts(GIT_OPT_SET_OWNER_VALIDATION, 1));
- cl_fixture_sandbox("testrepo.git");
+ cl_fixture_sandbox("empty_standard_repo");
+ cl_git_pass(cl_rename("empty_standard_repo/.gitted", "empty_standard_repo/.git"));
+
+ /*
+ * On Windows, we can generally map a local drive to a UNC path;
+ * for example C:\Foo\Bar becomes //localhost/C$/Foo/bar
+ */
+ cl_git_pass(git_str_printf(&unc_path, "//localhost/%s/%s",
+ clar_sandbox_path(), "empty_standard_repo"));
+
+ if (unc_path.ptr[13] != ':' || unc_path.ptr[14] != '/')
+ cl_skip();
+
+ unc_path.ptr[13] = '$';
git_fs_path__set_owner(GIT_FS_PATH_OWNER_OTHER);
- cl_git_fail_with(
- GIT_EOWNER, git_repository_open(&repo, "testrepo.git"));
+ cl_git_fail_with(GIT_EOWNER, git_repository_open(&repo, unc_path.ptr));
/* Add safe.directory options to the global configuration */
git_str_joinpath(&config_path, clar_sandbox_path(), "__global_config");
cl_must_pass(p_mkdir(config_path.ptr, 0777));
- git_libgit2_opts(
- GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL,
- config_path.ptr);
+ git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, config_path.ptr);
git_str_joinpath(&config_filename, config_path.ptr, ".gitconfig");
- cl_git_rewritefile(config_filename.ptr, "[foo]\n"
- "\tbar = Foobar\n"
- "\tbaz = Baz!\n"
- "[safe]\n"
- "\tdirectory = *\n"
- "[bar]\n"
- "\tfoo = barfoo\n");
+ /* The blank resets our sandbox directory and opening fails */
- cl_git_pass(git_repository_open(&repo, "testrepo.git"));
+ git_str_printf(&config_data,
+ "[safe]\n\tdirectory = %s\n",
+ unc_path.ptr);
+ cl_git_rewritefile(config_filename.ptr, config_data.ptr);
+
+ cl_git_pass(git_repository_open(&repo, unc_path.ptr));
git_repository_free(repo);
git_str_dispose(&config_path);
git_str_dispose(&config_filename);
+ git_str_dispose(&config_data);
+ git_str_dispose(&unc_path);
+#endif
}
void test_repo_open__can_reset_safe_directory_list(void)
diff --git a/tests/libgit2/repo/shallow.c b/tests/libgit2/repo/shallow.c
index adb7a9e..a3e3036 100644
--- a/tests/libgit2/repo/shallow.c
+++ b/tests/libgit2/repo/shallow.c
@@ -35,5 +35,5 @@ void test_repo_shallow__clears_errors(void)
{
g_repo = cl_git_sandbox_init("testrepo.git");
cl_assert_equal_i(0, git_repository_is_shallow(g_repo));
- cl_assert_equal_p(NULL, git_error_last());
+ cl_assert_equal_i(GIT_ERROR_NONE, git_error_last()->klass);
}
diff --git a/tests/libgit2/revert/workdir.c b/tests/libgit2/revert/workdir.c
index 3e790b7..6d74254 100644
--- a/tests/libgit2/revert/workdir.c
+++ b/tests/libgit2/revert/workdir.c
@@ -188,7 +188,7 @@ void test_revert_workdir__again(void)
cl_git_pass(git_tree_lookup(&reverted_tree, repo, &reverted_tree_oid));
cl_git_pass(git_signature_new(&signature, "Reverter", "reverter@example.org", time(NULL), 0));
- cl_git_pass(git_commit_create(&reverted_commit_oid, repo, "HEAD", signature, signature, NULL, "Reverted!", reverted_tree, 1, (const git_commit **)&orig_head));
+ cl_git_pass(git_commit_create(&reverted_commit_oid, repo, "HEAD", signature, signature, NULL, "Reverted!", reverted_tree, 1, &orig_head));
cl_git_pass(git_revert(repo, orig_head, NULL));
cl_assert(merge_test_index(repo_index, merge_index_entries, 4));
@@ -238,7 +238,7 @@ void test_revert_workdir__again_after_automerge(void)
cl_git_pass(git_tree_lookup(&reverted_tree, repo, &reverted_tree_oid));
cl_git_pass(git_signature_new(&signature, "Reverter", "reverter@example.org", time(NULL), 0));
- cl_git_pass(git_commit_create(&reverted_commit_oid, repo, "HEAD", signature, signature, NULL, "Reverted!", reverted_tree, 1, (const git_commit **)&head));
+ cl_git_pass(git_commit_create(&reverted_commit_oid, repo, "HEAD", signature, signature, NULL, "Reverted!", reverted_tree, 1, &head));
cl_git_pass(git_revert(repo, commit, NULL));
cl_assert(merge_test_index(repo_index, second_revert_entries, 6));
@@ -287,7 +287,7 @@ void test_revert_workdir__again_after_edit(void)
cl_git_pass(git_tree_lookup(&reverted_tree, repo, &reverted_tree_oid));
cl_git_pass(git_signature_new(&signature, "Reverter", "reverter@example.org", time(NULL), 0));
- cl_git_pass(git_commit_create(&reverted_commit_oid, repo, "HEAD", signature, signature, NULL, "Reverted!", reverted_tree, 1, (const git_commit **)&orig_head));
+ cl_git_pass(git_commit_create(&reverted_commit_oid, repo, "HEAD", signature, signature, NULL, "Reverted!", reverted_tree, 1, &orig_head));
cl_git_pass(git_revert(repo, commit, NULL));
cl_assert(merge_test_index(repo_index, merge_index_entries, 4));
diff --git a/tests/libgit2/revwalk/basic.c b/tests/libgit2/revwalk/basic.c
index 41090a1..5c53405 100644
--- a/tests/libgit2/revwalk/basic.c
+++ b/tests/libgit2/revwalk/basic.c
@@ -550,8 +550,7 @@ void test_revwalk_basic__big_timestamp(void)
cl_git_pass(git_signature_new(&sig, "Joe", "joe@example.com", INT64_C(2399662595), 0));
cl_git_pass(git_commit_tree(&tree, tip));
- cl_git_pass(git_commit_create(&id, _repo, "HEAD", sig, sig, NULL, "some message", tree, 1,
- (const git_commit **)&tip));
+ cl_git_pass(git_commit_create(&id, _repo, "HEAD", sig, sig, NULL, "some message", tree, 1, &tip));
cl_git_pass(git_revwalk_push_head(_walk));
diff --git a/tests/libgit2/status/worktree.c b/tests/libgit2/status/worktree.c
index efbf597..8a2ea9c 100644
--- a/tests/libgit2/status/worktree.c
+++ b/tests/libgit2/status/worktree.c
@@ -1360,3 +1360,13 @@ void test_status_worktree__at_head_parent(void)
git_tree_free(parent_tree);
git_status_list_free(statuslist);
}
+
+void test_status_worktree__skip_hash(void)
+{
+ git_repository *repo = cl_git_sandbox_init("status_skiphash");
+ git_index *index;
+
+ cl_git_pass(git_repository_index(&index, repo));
+ cl_git_pass(git_index_read(index, true));
+ git_index_free(index);
+}
diff --git a/tests/libgit2/submodule/lookup.c b/tests/libgit2/submodule/lookup.c
index febb7df..14a624b 100644
--- a/tests/libgit2/submodule/lookup.c
+++ b/tests/libgit2/submodule/lookup.c
@@ -401,6 +401,24 @@ void test_submodule_lookup__prefix_name(void)
git_submodule_free(sm);
}
+/* ".path" in name of submodule */
+void test_submodule_lookup__dotpath_in_name(void)
+{
+ sm_lookup_data data;
+
+ cl_git_rewritefile(
+ "submod2/.gitmodules", "[submodule \"kwb.pathdict\"]\n"
+ " path = kwb.pathdict\n"
+ " url = ../Test_App\n"
+ "[submodule \"fakin.path.app\"]\n"
+ " path = fakin.path.app\n"
+ " url = ../Test_App\n");
+
+ memset(&data, 0, sizeof(data));
+ cl_git_pass(git_submodule_foreach(g_repo, sm_lookup_cb, &data));
+ cl_assert_equal_i(9, data.count);
+}
+
void test_submodule_lookup__renamed(void)
{
const char *newpath = "sm_actually_changed";
diff --git a/tests/libgit2/trace/trace.c b/tests/libgit2/trace/trace.c
index 097208b..9fea576 100644
--- a/tests/libgit2/trace/trace.c
+++ b/tests/libgit2/trace/trace.c
@@ -32,16 +32,11 @@ void test_trace_trace__cleanup(void)
void test_trace_trace__sets(void)
{
-#ifdef GIT_TRACE
cl_assert(git_trace_level() == GIT_TRACE_INFO);
-#else
- cl_skip();
-#endif
}
void test_trace_trace__can_reset(void)
{
-#ifdef GIT_TRACE
cl_assert(git_trace_level() == GIT_TRACE_INFO);
cl_git_pass(git_trace_set(GIT_TRACE_ERROR, trace_callback));
@@ -51,14 +46,10 @@ void test_trace_trace__can_reset(void)
git_trace(GIT_TRACE_ERROR, "Hello %s!", "world");
cl_assert(written == 1);
-#else
- cl_skip();
-#endif
}
void test_trace_trace__can_unset(void)
{
-#ifdef GIT_TRACE
cl_assert(git_trace_level() == GIT_TRACE_INFO);
cl_git_pass(git_trace_set(GIT_TRACE_NONE, NULL));
@@ -67,40 +58,25 @@ void test_trace_trace__can_unset(void)
cl_assert(written == 0);
git_trace(GIT_TRACE_FATAL, "Hello %s!", "world");
cl_assert(written == 0);
-#else
- cl_skip();
-#endif
}
void test_trace_trace__skips_higher_level(void)
{
-#ifdef GIT_TRACE
cl_assert(written == 0);
git_trace(GIT_TRACE_DEBUG, "Hello %s!", "world");
cl_assert(written == 0);
-#else
- cl_skip();
-#endif
}
void test_trace_trace__writes(void)
{
-#ifdef GIT_TRACE
cl_assert(written == 0);
git_trace(GIT_TRACE_INFO, "Hello %s!", "world");
cl_assert(written == 1);
-#else
- cl_skip();
-#endif
}
void test_trace_trace__writes_lower_level(void)
{
-#ifdef GIT_TRACE
cl_assert(written == 0);
git_trace(GIT_TRACE_ERROR, "Hello %s!", "world");
cl_assert(written == 1);
-#else
- cl_skip();
-#endif
}
diff --git a/tests/libgit2/transport/ssh_exec.c b/tests/libgit2/transport/ssh_exec.c
new file mode 100644
index 0000000..886c10a
--- /dev/null
+++ b/tests/libgit2/transport/ssh_exec.c
@@ -0,0 +1,79 @@
+#include "clar_libgit2.h"
+#include "git2/sys/remote.h"
+#include "git2/sys/transport.h"
+
+
+void test_transport_ssh_exec__reject_injection_username(void)
+{
+#ifndef GIT_SSH_EXEC
+ cl_skip();
+#else
+ git_remote *remote;
+ git_repository *repo;
+ git_transport *transport;
+ const char *url = "-oProxyCommand=git@somehost:somepath";
+ git_remote_connect_options opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
+
+
+ cl_git_pass(git_repository_init(&repo, "./transport-username", 0));
+ cl_git_pass(git_remote_create(&remote, repo, "test",
+ cl_fixture("testrepo.git")));
+ cl_git_pass(git_transport_new(&transport, remote, url));
+ cl_git_fail_with(-1, transport->connect(transport, url,
+ GIT_SERVICE_UPLOADPACK_LS, &opts));
+
+ transport->free(transport);
+ git_remote_free(remote);
+ git_repository_free(repo);
+#endif
+}
+
+void test_transport_ssh_exec__reject_injection_hostname(void)
+{
+#ifndef GIT_SSH_EXEC
+ cl_skip();
+#else
+ git_remote *remote;
+ git_repository *repo;
+ git_transport *transport;
+ const char *url = "-oProxyCommand=somehost:somepath-hostname";
+ git_remote_connect_options opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
+
+
+ cl_git_pass(git_repository_init(&repo, "./transport-hostname", 0));
+ cl_git_pass(git_remote_create(&remote, repo, "test",
+ cl_fixture("testrepo.git")));
+ cl_git_pass(git_transport_new(&transport, remote, url));
+ cl_git_fail_with(-1, transport->connect(transport, url,
+ GIT_SERVICE_UPLOADPACK_LS, &opts));
+
+ transport->free(transport);
+ git_remote_free(remote);
+ git_repository_free(repo);
+#endif
+}
+
+void test_transport_ssh_exec__reject_injection_path(void)
+{
+#ifndef GIT_SSH_EXEC
+ cl_skip();
+#else
+ git_remote *remote;
+ git_repository *repo;
+ git_transport *transport;
+ const char *url = "git@somehost:-somepath";
+ git_remote_connect_options opts = GIT_REMOTE_CONNECT_OPTIONS_INIT;
+
+
+ cl_git_pass(git_repository_init(&repo, "./transport-path", 0));
+ cl_git_pass(git_remote_create(&remote, repo, "test",
+ cl_fixture("testrepo.git")));
+ cl_git_pass(git_transport_new(&transport, remote, url));
+ cl_git_fail_with(-1, transport->connect(transport, url,
+ GIT_SERVICE_UPLOADPACK_LS, &opts));
+
+ transport->free(transport);
+ git_remote_free(remote);
+ git_repository_free(repo);
+#endif
+}
diff --git a/tests/libgit2/worktree/config.c b/tests/libgit2/worktree/config.c
index 81dcfe1..1fd1f75 100644
--- a/tests/libgit2/worktree/config.c
+++ b/tests/libgit2/worktree/config.c
@@ -6,15 +6,19 @@
static worktree_fixture fixture =
WORKTREE_FIXTURE_INIT(COMMON_REPO, WORKTREE_REPO);
+static worktree_fixture submodule =
+ WORKTREE_FIXTURE_INIT("submodules", "submodules-worktree-parent");
void test_worktree_config__initialize(void)
{
setup_fixture_worktree(&fixture);
+ setup_fixture_worktree(&submodule);
}
void test_worktree_config__cleanup(void)
{
cleanup_fixture_worktree(&fixture);
+ cleanup_fixture_worktree(&submodule);
}
void test_worktree_config__open(void)
@@ -27,7 +31,7 @@ void test_worktree_config__open(void)
git_config_free(cfg);
}
-void test_worktree_config__set(void)
+void test_worktree_config__set_level_local(void)
{
git_config *cfg;
int32_t val;
@@ -45,3 +49,78 @@ void test_worktree_config__set(void)
cl_assert_equal_i(val, 5);
git_config_free(cfg);
}
+
+void test_worktree_config__requires_extension(void)
+{
+ git_config *cfg;
+ git_config *wtcfg;
+ int extension = 0;
+
+ /*
+ * the "submodules" repo does not have extensions.worktreeconfig
+ * set, the worktree configuration should not be available.
+ */
+ cl_git_pass(git_repository_config(&cfg, submodule.repo));
+ cl_git_fail_with(GIT_ENOTFOUND, git_config_get_bool(&extension, cfg, "extensions.worktreeconfig"));
+ cl_assert_equal_i(0, extension);
+ cl_git_fail_with(GIT_ENOTFOUND, git_config_open_level(&wtcfg, cfg, GIT_CONFIG_LEVEL_WORKTREE));
+ git_config_free(cfg);
+
+ /* the "testrepo" repo does have the configuration set. */
+ cl_git_pass(git_repository_config(&cfg, fixture.repo));
+ cl_git_pass(git_config_get_bool(&extension, cfg, "extensions.worktreeconfig"));
+ cl_assert_equal_i(1, extension);
+ cl_git_pass(git_config_open_level(&wtcfg, cfg, GIT_CONFIG_LEVEL_WORKTREE));
+ git_config_free(wtcfg);
+ git_config_free(cfg);
+}
+
+void test_worktree_config__exists(void)
+{
+ git_config *cfg, *wtcfg, *snap;
+ const char *str;
+
+ cl_git_pass(git_repository_config(&cfg, fixture.repo));
+ cl_git_pass(git_repository_config(&wtcfg, fixture.worktree));
+
+ cl_git_pass(git_config_snapshot(&snap, cfg));
+ cl_git_pass(git_config_get_string(&str, snap, "worktreetest.config"));
+ cl_assert_equal_s("mainrepo", str);
+ git_config_free(snap);
+
+ cl_git_pass(git_config_snapshot(&snap, wtcfg));
+ cl_git_pass(git_config_get_string(&str, snap, "worktreetest.config"));
+ cl_assert_equal_s("worktreerepo", str);
+ git_config_free(snap);
+
+ git_config_free(cfg);
+ git_config_free(wtcfg);
+}
+
+void test_worktree_config__set_level_worktree(void)
+{
+ git_config *cfg;
+ git_config *wtcfg;
+ int32_t val;
+
+ cl_git_pass(git_repository_config(&cfg, fixture.repo));
+ cl_git_pass(git_config_open_level(&wtcfg, cfg, GIT_CONFIG_LEVEL_WORKTREE));
+ cl_git_pass(git_config_set_int32(wtcfg, "worktree.specific", 42));
+
+ cl_git_pass(git_config_get_int32(&val, cfg, "worktree.specific"));
+ cl_assert_equal_i(val, 42);
+
+ /* reopen to verify config has been set */
+ git_config_free(cfg);
+ cl_git_pass(git_repository_config(&cfg, fixture.repo));
+ cl_git_pass(git_config_get_int32(&val, cfg, "worktree.specific"));
+ cl_assert_equal_i(val, 42);
+
+ cl_git_fail_with(GIT_ENOTFOUND, git_config_delete_entry(cfg, "worktree.specific"));
+
+ cl_git_pass(git_config_delete_entry(wtcfg, "worktree.specific"));
+ cl_git_fail_with(GIT_ENOTFOUND, git_config_get_int32(&val, cfg, "worktree.specific"));
+
+ git_config_free(cfg);
+ git_config_free(wtcfg);
+}
diff --git a/tests/libgit2/worktree/refs.c b/tests/libgit2/worktree/refs.c
index 557726a..51e7b2b 100644
--- a/tests/libgit2/worktree/refs.c
+++ b/tests/libgit2/worktree/refs.c
@@ -20,7 +20,7 @@ void test_worktree_refs__cleanup(void)
cleanup_fixture_worktree(&fixture);
}
-void test_worktree_refs__list(void)
+void test_worktree_refs__list_no_difference_in_worktree(void)
{
git_strarray refs, wtrefs;
unsigned i, j;
@@ -61,6 +61,66 @@ exit:
cl_git_pass(error);
}
+void test_worktree_refs__list_worktree_specific(void)
+{
+ git_strarray refs, wtrefs;
+ git_reference *ref, *new_branch;
+ int error = 0;
+ git_oid oid;
+
+ cl_git_pass(git_reference_name_to_id(&oid, fixture.repo, "refs/heads/dir"));
+ cl_git_fail_with(GIT_ENOTFOUND, git_reference_lookup(&ref, fixture.repo, "refs/bisect/a-bisect-ref"));
+ cl_git_pass(git_reference_create(
+ &new_branch, fixture.worktree, "refs/bisect/a-bisect-ref", &oid,
+ 0, "test"));
+
+ cl_git_fail_with(GIT_ENOTFOUND, git_reference_lookup(&ref, fixture.repo, "refs/bisect/a-bisect-ref"));
+ cl_git_pass(git_reference_lookup(&ref, fixture.worktree, "refs/bisect/a-bisect-ref"));
+
+ cl_git_pass(git_reference_list(&refs, fixture.repo));
+ cl_git_pass(git_reference_list(&wtrefs, fixture.worktree));
+
+ cl_assert_equal_sz(wtrefs.count, refs.count + 1);
+
+ git_reference_free(ref);
+ git_reference_free(new_branch);
+ git_strarray_dispose(&refs);
+ git_strarray_dispose(&wtrefs);
+ cl_git_pass(error);
+}
+
+void test_worktree_refs__list_worktree_specific_hidden_in_main_repo(void)
+{
+ git_strarray refs, wtrefs;
+ git_reference *ref, *new_branch;
+ int error = 0;
+ git_oid oid;
+
+ cl_git_pass(
+ git_reference_name_to_id(&oid, fixture.repo, "refs/heads/dir"));
+ cl_git_fail_with(GIT_ENOTFOUND, git_reference_lookup(
+ &ref, fixture.worktree, "refs/bisect/a-bisect-ref"));
+ cl_git_pass(git_reference_create(
+ &new_branch, fixture.repo, "refs/bisect/a-bisect-ref", &oid,
+ 0, "test"));
+
+ cl_git_fail_with(GIT_ENOTFOUND, git_reference_lookup(
+ &ref, fixture.worktree, "refs/bisect/a-bisect-ref"));
+ cl_git_pass(git_reference_lookup(
+ &ref, fixture.repo, "refs/bisect/a-bisect-ref"));
+
+ cl_git_pass(git_reference_list(&refs, fixture.repo));
+ cl_git_pass(git_reference_list(&wtrefs, fixture.worktree));
+
+ cl_assert_equal_sz(refs.count, wtrefs.count + 1);
+
+ git_reference_free(ref);
+ git_reference_free(new_branch);
+ git_strarray_dispose(&refs);
+ git_strarray_dispose(&wtrefs);
+ cl_git_pass(error);
+}
+
void test_worktree_refs__read_head(void)
{
git_reference *head;
diff --git a/tests/libgit2/worktree/worktree.c b/tests/libgit2/worktree/worktree.c
index fed5c92..00e3e3f 100644
--- a/tests/libgit2/worktree/worktree.c
+++ b/tests/libgit2/worktree/worktree.c
@@ -217,6 +217,50 @@ void test_worktree_worktree__init(void)
git_repository_free(repo);
}
+void test_worktree_worktree__add_remove_add(void)
+{
+ git_worktree_add_options add_opts = GIT_WORKTREE_ADD_OPTIONS_INIT;
+ git_worktree_prune_options opts = GIT_WORKTREE_PRUNE_OPTIONS_INIT;
+ git_str path = GIT_BUF_INIT;
+ git_reference *branch;
+ git_repository *repo;
+ git_worktree *wt;
+
+ /* Add the worktree */
+ cl_git_pass(git_str_joinpath(&path, fixture.repo->workdir, "../worktree-add-remove-add"));
+ cl_git_pass(git_worktree_add(&wt, fixture.repo, "worktree-add-remove-add", path.ptr, NULL));
+
+ /* Open and verify created repo */
+ cl_git_pass(git_repository_open(&repo, path.ptr));
+ cl_assert(git__suffixcmp(git_repository_workdir(repo), "worktree-add-remove-add/") == 0);
+ cl_git_pass(git_branch_lookup(&branch, repo, "worktree-add-remove-add", GIT_BRANCH_LOCAL));
+ git_reference_free(branch);
+ git_repository_free(repo);
+
+ /* Prune the worktree */
+ opts.flags = GIT_WORKTREE_PRUNE_VALID|GIT_WORKTREE_PRUNE_WORKING_TREE;
+ cl_git_pass(git_worktree_prune(wt, &opts));
+ cl_assert(!git_fs_path_exists(wt->gitdir_path));
+ cl_assert(!git_fs_path_exists(wt->gitlink_path));
+ git_worktree_free(wt);
+
+ /* Add the worktree back with default options should fail. */
+ cl_git_fail(git_worktree_add(&wt, fixture.repo, "worktree-add-remove-add", path.ptr, &add_opts));
+ /* If allowing checkout of existing branches, it should succeed. */
+ add_opts.checkout_existing = 1;
+ cl_git_pass(git_worktree_add(&wt, fixture.repo, "worktree-add-remove-add", path.ptr, &add_opts));
+
+ /* Open and verify created repo */
+ cl_git_pass(git_repository_open(&repo, path.ptr));
+ cl_assert(git__suffixcmp(git_repository_workdir(repo), "worktree-add-remove-add/") == 0);
+ cl_git_pass(git_branch_lookup(&branch, repo, "worktree-add-remove-add", GIT_BRANCH_LOCAL));
+ git_reference_free(branch);
+ git_repository_free(repo);
+
+ git_str_dispose(&path);
+ git_worktree_free(wt);
+}
+
void test_worktree_worktree__add_locked(void)
{
git_worktree *wt;
@@ -244,6 +288,7 @@ void test_worktree_worktree__add_locked(void)
void test_worktree_worktree__init_existing_branch(void)
{
+ git_worktree_add_options opts = GIT_WORKTREE_ADD_OPTIONS_INIT;
git_reference *head, *branch;
git_commit *commit;
git_worktree *wt;
@@ -251,12 +296,18 @@ void test_worktree_worktree__init_existing_branch(void)
cl_git_pass(git_repository_head(&head, fixture.repo));
cl_git_pass(git_commit_lookup(&commit, fixture.repo, &head->target.oid));
- cl_git_pass(git_branch_create(&branch, fixture.repo, "worktree-new", commit, false));
+ cl_git_pass(git_branch_create(&branch, fixture.repo, "worktree-new-exist", commit, false));
- cl_git_pass(git_str_joinpath(&path, fixture.repo->workdir, "../worktree-new"));
- cl_git_fail(git_worktree_add(&wt, fixture.repo, "worktree-new", path.ptr, NULL));
+ cl_git_pass(git_str_joinpath(&path, fixture.repo->workdir, "../worktree-new-exist"));
+
+ /* Add the worktree back with default options should fail. */
+ cl_git_fail(git_worktree_add(&wt, fixture.repo, "worktree-new-exist", path.ptr, NULL));
+ /* If allowing checkout of existing branches, it should succeed. */
+ opts.checkout_existing = 1;
+ cl_git_pass(git_worktree_add(&wt, fixture.repo, "worktree-new-exist", path.ptr, &opts));
git_str_dispose(&path);
+ git_worktree_free(wt);
git_commit_free(commit);
git_reference_free(head);
git_reference_free(branch);
diff --git a/tests/resources/merge-resolve/.gitted/objects/29 b/tests/resources/merge-resolve/.gitted/objects/29
new file mode 100644
index 0000000..9661507
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/29
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/54/c9d15687fb4f56e08252662962d6d1dbc09d9d b/tests/resources/merge-resolve/.gitted/objects/54/c9d15687fb4f56e08252662962d6d1dbc09d9d
new file mode 100644
index 0000000..7e0555b
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/54/c9d15687fb4f56e08252662962d6d1dbc09d9d
@@ -0,0 +1,3 @@
+x¥NI
+1ôœWô]žì/þÀ´Žãa&#~ß(þÀ:ÕFQ\—åÖAÛ¸éMtrš8K0Y›àK&Ž¥Xk¢w—É™"è$pPwj²vÕ\RðhÑgI=ŘK*SDaMÚ*zö¹68åµ ç¹.ºÂ^†ûaGù?µãº`
+­q6YØâ€î8ÛåÏÅ3­W^áBM½ùiQ† \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/objects/57/16ca5987cbf97d6bb54920bea6adde242d87e6 b/tests/resources/merge-resolve/.gitted/objects/57/16ca5987cbf97d6bb54920bea6adde242d87e6
new file mode 100644
index 0000000..cfc3920
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/57/16ca5987cbf97d6bb54920bea6adde242d87e6
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/60/b12be2d2f57977ce83d8dfd32e2394ac1ba1a2 b/tests/resources/merge-resolve/.gitted/objects/60/b12be2d2f57977ce83d8dfd32e2394ac1ba1a2
new file mode 100644
index 0000000..f53f75e
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/60/b12be2d2f57977ce83d8dfd32e2394ac1ba1a2
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/a6/5140d5ec9f47064f614ecf8e43776baa5c0c11 b/tests/resources/merge-resolve/.gitted/objects/a6/5140d5ec9f47064f614ecf8e43776baa5c0c11
new file mode 100644
index 0000000..dc6cf64
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/a6/5140d5ec9f47064f614ecf8e43776baa5c0c11
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/ab/347abd8cda4a0e3b8bb42bb620c0c72c7df779 b/tests/resources/merge-resolve/.gitted/objects/ab/347abd8cda4a0e3b8bb42bb620c0c72c7df779
new file mode 100644
index 0000000..d743a38
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/ab/347abd8cda4a0e3b8bb42bb620c0c72c7df779
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/bc/114411903fd2afaa4bb9b85ed13f27e37ac375 b/tests/resources/merge-resolve/.gitted/objects/bc/114411903fd2afaa4bb9b85ed13f27e37ac375
new file mode 100644
index 0000000..08941ff
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/bc/114411903fd2afaa4bb9b85ed13f27e37ac375
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/cd/edf9760406dc79e0c6a8899ce9f180ec2a23a0 b/tests/resources/merge-resolve/.gitted/objects/cd/edf9760406dc79e0c6a8899ce9f180ec2a23a0
new file mode 100644
index 0000000..011b5b3
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/cd/edf9760406dc79e0c6a8899ce9f180ec2a23a0
@@ -0,0 +1,2 @@
+x¥A
+B1C]÷³¤µÓö "n¼¨Ó)ÀþBÕë[ŘUò ÕR¤Ã^ÛMo̽3¨“c:d Úcö™òÄhCð·i2FÅGŸkƒKzÅ–à:ײÖŽ<èÇù[üÒŽj9 zBë0XØê!5è8ïü猒EºÄ;4~Ê*uQo—$DÝ \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/objects/de/06afe070b65f94d7d791c39a6d389c58dda60d b/tests/resources/merge-resolve/.gitted/objects/de/06afe070b65f94d7d791c39a6d389c58dda60d
new file mode 100644
index 0000000..28567b6
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/de/06afe070b65f94d7d791c39a6d389c58dda60d
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/e5/0a49f9558d09d4d3bfc108363bb24c127ed263 b/tests/resources/merge-resolve/.gitted/objects/e5/0a49f9558d09d4d3bfc108363bb24c127ed263
new file mode 100644
index 0000000..251c5df
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/e5/0a49f9558d09d4d3bfc108363bb24c127ed263
Binary files differ
diff --git a/tests/resources/merge-resolve/.gitted/objects/ea/789495e0a72efadcd0f86a48f4c9ed435bb8a3 b/tests/resources/merge-resolve/.gitted/objects/ea/789495e0a72efadcd0f86a48f4c9ed435bb8a3
new file mode 100644
index 0000000..ed98d70
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/objects/ea/789495e0a72efadcd0f86a48f4c9ed435bb8a3
@@ -0,0 +1,3 @@
+x¥OIj1ÌY¯è»!´¶‘Áøâä­V‹ÉA£ Ëøû–M~:ÕE÷Ö~&o>æÌZ;§uB[‹¡JärN9z)ÚVÄb¼ú¥!Ç.Rj
+:Ü
+‡$ÈŘKª:¢°!c ÝçÞ\˃Fï½·[?àK–ûbyê“{;ƒõÞ œpA-wòϵ–S[_iÀì{WOG‰Rï \ No newline at end of file
diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/emptyfile_renames b/tests/resources/merge-resolve/.gitted/refs/heads/emptyfile_renames
new file mode 100644
index 0000000..89b4eea
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/refs/heads/emptyfile_renames
@@ -0,0 +1 @@
+ea789495e0a72efadcd0f86a48f4c9ed435bb8a3
diff --git a/tests/resources/merge-resolve/.gitted/refs/heads/emptyfile_renames-branch b/tests/resources/merge-resolve/.gitted/refs/heads/emptyfile_renames-branch
new file mode 100644
index 0000000..1c6a9f4
--- /dev/null
+++ b/tests/resources/merge-resolve/.gitted/refs/heads/emptyfile_renames-branch
@@ -0,0 +1 @@
+ab347abd8cda4a0e3b8bb42bb620c0c72c7df779
diff --git a/tests/resources/process/cat.bat b/tests/resources/process/cat.bat
new file mode 100644
index 0000000..af9b573
--- /dev/null
+++ b/tests/resources/process/cat.bat
@@ -0,0 +1,2 @@
+@ECHO OFF
+FOR /F "tokens=*" %%a IN ('more') DO ECHO %%a
diff --git a/tests/resources/process/env.cmd b/tests/resources/process/env.cmd
new file mode 100644
index 0000000..62675cf
--- /dev/null
+++ b/tests/resources/process/env.cmd
@@ -0,0 +1,2 @@
+@ECHO OFF
+SET
diff --git a/tests/resources/process/helloworld.sh b/tests/resources/process/helloworld.sh
new file mode 100755
index 0000000..0c4aefc
--- /dev/null
+++ b/tests/resources/process/helloworld.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+echo "Hello, world."
diff --git a/tests/resources/process/pwd.bat b/tests/resources/process/pwd.bat
new file mode 100644
index 0000000..82e4fb6
--- /dev/null
+++ b/tests/resources/process/pwd.bat
@@ -0,0 +1,2 @@
+@ECHO OFF
+ECHO %CD%
diff --git a/tests/resources/push.sh b/tests/resources/push.sh
index 3e77fb5..648c2ad 100644
--- a/tests/resources/push.sh
+++ b/tests/resources/push.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
#creates push_src repo for libgit2 push tests.
set -eu
diff --git a/tests/resources/pushoptions.git/HEAD b/tests/resources/pushoptions.git/HEAD
new file mode 100644
index 0000000..b870d82
--- /dev/null
+++ b/tests/resources/pushoptions.git/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/main
diff --git a/tests/resources/pushoptions.git/branches/.gitignore b/tests/resources/pushoptions.git/branches/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/resources/pushoptions.git/branches/.gitignore
diff --git a/tests/resources/pushoptions.git/config b/tests/resources/pushoptions.git/config
new file mode 100644
index 0000000..23d3978
--- /dev/null
+++ b/tests/resources/pushoptions.git/config
@@ -0,0 +1,8 @@
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = true
+ ignorecase = true
+ precomposeunicode = true
+[receive]
+ advertisePushOptions = true
diff --git a/tests/resources/pushoptions.git/description b/tests/resources/pushoptions.git/description
new file mode 100644
index 0000000..498b267
--- /dev/null
+++ b/tests/resources/pushoptions.git/description
@@ -0,0 +1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff --git a/tests/resources/pushoptions.git/hooks/pre-receive b/tests/resources/pushoptions.git/hooks/pre-receive
new file mode 100755
index 0000000..24f48d3
--- /dev/null
+++ b/tests/resources/pushoptions.git/hooks/pre-receive
@@ -0,0 +1,3 @@
+#!/bin/sh
+printf "${GIT_PUSH_OPTION_1}${GIT_PUSH_OPTION_2}${GIT_PUSH_OPTION_3}" > "${GIT_PUSH_OPTION_0}"
+exit 0
diff --git a/tests/resources/pushoptions.git/info/exclude b/tests/resources/pushoptions.git/info/exclude
new file mode 100644
index 0000000..a5196d1
--- /dev/null
+++ b/tests/resources/pushoptions.git/info/exclude
@@ -0,0 +1,6 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
diff --git a/tests/resources/pushoptions.git/objects/info/.gitignore b/tests/resources/pushoptions.git/objects/info/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/resources/pushoptions.git/objects/info/.gitignore
diff --git a/tests/resources/pushoptions.git/objects/pack/.gitignore b/tests/resources/pushoptions.git/objects/pack/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/resources/pushoptions.git/objects/pack/.gitignore
diff --git a/tests/resources/pushoptions.git/refs/heads/.gitignore b/tests/resources/pushoptions.git/refs/heads/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/resources/pushoptions.git/refs/heads/.gitignore
diff --git a/tests/resources/pushoptions.git/refs/tags/.gitignore b/tests/resources/pushoptions.git/refs/tags/.gitignore
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/resources/pushoptions.git/refs/tags/.gitignore
diff --git a/tests/resources/status_skiphash/.gitted/COMMIT_EDITMSG b/tests/resources/status_skiphash/.gitted/COMMIT_EDITMSG
new file mode 100644
index 0000000..ea450f9
--- /dev/null
+++ b/tests/resources/status_skiphash/.gitted/COMMIT_EDITMSG
@@ -0,0 +1 @@
+New file
diff --git a/tests/resources/status_skiphash/.gitted/HEAD b/tests/resources/status_skiphash/.gitted/HEAD
new file mode 100644
index 0000000..b870d82
--- /dev/null
+++ b/tests/resources/status_skiphash/.gitted/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/main
diff --git a/tests/resources/status_skiphash/.gitted/MERGE_RR b/tests/resources/status_skiphash/.gitted/MERGE_RR
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/resources/status_skiphash/.gitted/MERGE_RR
diff --git a/tests/resources/status_skiphash/.gitted/config b/tests/resources/status_skiphash/.gitted/config
new file mode 100644
index 0000000..16aebb6
--- /dev/null
+++ b/tests/resources/status_skiphash/.gitted/config
@@ -0,0 +1,9 @@
+[core]
+ repositoryformatversion = 0
+ filemode = false
+ bare = false
+ logallrefupdates = true
+ symlinks = false
+ ignorecase = true
+[index]
+ skipHash = true
diff --git a/tests/resources/status_skiphash/.gitted/description b/tests/resources/status_skiphash/.gitted/description
new file mode 100644
index 0000000..498b267
--- /dev/null
+++ b/tests/resources/status_skiphash/.gitted/description
@@ -0,0 +1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff --git a/tests/resources/status_skiphash/.gitted/index b/tests/resources/status_skiphash/.gitted/index
new file mode 100644
index 0000000..1963fe0
--- /dev/null
+++ b/tests/resources/status_skiphash/.gitted/index
Binary files differ
diff --git a/tests/resources/status_skiphash/.gitted/info/exclude b/tests/resources/status_skiphash/.gitted/info/exclude
new file mode 100644
index 0000000..a5196d1
--- /dev/null
+++ b/tests/resources/status_skiphash/.gitted/info/exclude
@@ -0,0 +1,6 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
diff --git a/tests/resources/status_skiphash/.gitted/logs/HEAD b/tests/resources/status_skiphash/.gitted/logs/HEAD
new file mode 100644
index 0000000..35e1a74
--- /dev/null
+++ b/tests/resources/status_skiphash/.gitted/logs/HEAD
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 34f4c90b237fcb4c677772a6093f3cba239c41a5 Parnic <github@parnic.com> 1708097798 -0600 commit (initial): New file
diff --git a/tests/resources/status_skiphash/.gitted/logs/refs/heads/main b/tests/resources/status_skiphash/.gitted/logs/refs/heads/main
new file mode 100644
index 0000000..35e1a74
--- /dev/null
+++ b/tests/resources/status_skiphash/.gitted/logs/refs/heads/main
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 34f4c90b237fcb4c677772a6093f3cba239c41a5 Parnic <github@parnic.com> 1708097798 -0600 commit (initial): New file
diff --git a/tests/resources/status_skiphash/.gitted/objects/34/f4c90b237fcb4c677772a6093f3cba239c41a5 b/tests/resources/status_skiphash/.gitted/objects/34/f4c90b237fcb4c677772a6093f3cba239c41a5
new file mode 100644
index 0000000..0513158
--- /dev/null
+++ b/tests/resources/status_skiphash/.gitted/objects/34/f4c90b237fcb4c677772a6093f3cba239c41a5
Binary files differ
diff --git a/tests/resources/status_skiphash/.gitted/objects/71/a21e67674e9717aa7380e5782ec5e070a8d7e0 b/tests/resources/status_skiphash/.gitted/objects/71/a21e67674e9717aa7380e5782ec5e070a8d7e0
new file mode 100644
index 0000000..7c48fa4
--- /dev/null
+++ b/tests/resources/status_skiphash/.gitted/objects/71/a21e67674e9717aa7380e5782ec5e070a8d7e0
Binary files differ
diff --git a/tests/resources/status_skiphash/.gitted/objects/d7/c1f165e51adbbfd7760162b7a5802d4117740c b/tests/resources/status_skiphash/.gitted/objects/d7/c1f165e51adbbfd7760162b7a5802d4117740c
new file mode 100644
index 0000000..c685321
--- /dev/null
+++ b/tests/resources/status_skiphash/.gitted/objects/d7/c1f165e51adbbfd7760162b7a5802d4117740c
Binary files differ
diff --git a/tests/resources/status_skiphash/.gitted/refs/heads/main b/tests/resources/status_skiphash/.gitted/refs/heads/main
new file mode 100644
index 0000000..693a12b
--- /dev/null
+++ b/tests/resources/status_skiphash/.gitted/refs/heads/main
@@ -0,0 +1 @@
+34f4c90b237fcb4c677772a6093f3cba239c41a5
diff --git a/tests/resources/status_skiphash/new_file b/tests/resources/status_skiphash/new_file
new file mode 100644
index 0000000..badcfca
--- /dev/null
+++ b/tests/resources/status_skiphash/new_file
@@ -0,0 +1 @@
+new_file
diff --git a/tests/resources/testrepo/.gitted/config b/tests/resources/testrepo/.gitted/config
index d011401..04d750a 100644
--- a/tests/resources/testrepo/.gitted/config
+++ b/tests/resources/testrepo/.gitted/config
@@ -3,6 +3,8 @@
filemode = true
bare = false
logallrefupdates = true
+[extensions]
+ worktreeconfig = true
[remote "test"]
url = git://github.com/libgit2/libgit2
fetch = +refs/heads/*:refs/remotes/test/*
diff --git a/tests/resources/testrepo/.gitted/config.worktree b/tests/resources/testrepo/.gitted/config.worktree
new file mode 100644
index 0000000..df9f0ca
--- /dev/null
+++ b/tests/resources/testrepo/.gitted/config.worktree
@@ -0,0 +1,2 @@
+[worktreetest]
+ config = mainrepo
diff --git a/tests/resources/testrepo/.gitted/worktrees/testrepo-worktree/config.worktree b/tests/resources/testrepo/.gitted/worktrees/testrepo-worktree/config.worktree
new file mode 100644
index 0000000..7a130a7
--- /dev/null
+++ b/tests/resources/testrepo/.gitted/worktrees/testrepo-worktree/config.worktree
@@ -0,0 +1,2 @@
+[worktreetest]
+ config = worktreerepo
diff --git a/tests/util/assert.c b/tests/util/assert.c
index 3babc47..4644f35 100644
--- a/tests/util/assert.c
+++ b/tests/util/assert.c
@@ -92,7 +92,8 @@ void test_assert__argument_with_void_return_type(void)
git_error_clear();
cl_assert_equal_p(foo, fn_returns_string(foo));
- cl_assert_equal_p(NULL, git_error_last());
+ cl_assert_equal_i(GIT_ERROR_NONE, git_error_last()->klass);
+ cl_assert_equal_s("no error", git_error_last()->message);
}
void test_assert__internal(void)
diff --git a/tests/util/errors.c b/tests/util/errors.c
index 78654a7..f9b85a6 100644
--- a/tests/util/errors.c
+++ b/tests/util/errors.c
@@ -5,7 +5,10 @@ void test_errors__public_api(void)
char *str_in_error;
git_error_clear();
- cl_assert(git_error_last() == NULL);
+
+ cl_assert(git_error_last() != NULL);
+ cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
+ cl_assert(strcmp(git_error_last()->message, "no error") == 0);
git_error_set_oom();
@@ -23,7 +26,9 @@ void test_errors__public_api(void)
cl_assert(str_in_error != NULL);
git_error_clear();
- cl_assert(git_error_last() == NULL);
+ cl_assert(git_error_last() != NULL);
+ cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
+ cl_assert(strcmp(git_error_last()->message, "no error") == 0);
}
#include "common.h"
@@ -35,7 +40,9 @@ void test_errors__new_school(void)
char *str_in_error;
git_error_clear();
- cl_assert(git_error_last() == NULL);
+ cl_assert(git_error_last() != NULL);
+ cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
+ cl_assert(strcmp(git_error_last()->message, "no error") == 0);
git_error_set_oom(); /* internal fn */
@@ -53,7 +60,9 @@ void test_errors__new_school(void)
cl_assert(str_in_error != NULL);
git_error_clear();
- cl_assert(git_error_last() == NULL);
+ cl_assert(git_error_last() != NULL);
+ cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
+ cl_assert(strcmp(git_error_last()->message, "no error") == 0);
do {
struct stat st;
@@ -88,52 +97,32 @@ void test_errors__new_school(void)
void test_errors__restore(void)
{
- git_error_state err_state = {0};
+ git_error *last_error;
git_error_clear();
- cl_assert(git_error_last() == NULL);
-
- cl_assert_equal_i(0, git_error_state_capture(&err_state, 0));
-
- memset(&err_state, 0x0, sizeof(git_error_state));
+ cl_assert(git_error_last() != NULL);
+ cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
+ cl_assert(strcmp("no error", git_error_last()->message) == 0);
git_error_set(42, "Foo: %s", "bar");
- cl_assert_equal_i(-1, git_error_state_capture(&err_state, -1));
-
- cl_assert(git_error_last() == NULL);
-
- git_error_set(99, "Bar: %s", "foo");
-
- git_error_state_restore(&err_state);
-
- cl_assert_equal_i(42, git_error_last()->klass);
- cl_assert_equal_s("Foo: bar", git_error_last()->message);
-}
-
-void test_errors__free_state(void)
-{
- git_error_state err_state = {0};
+ cl_assert(git_error_save(&last_error) == 0);
git_error_clear();
-
- git_error_set(42, "Foo: %s", "bar");
- cl_assert_equal_i(-1, git_error_state_capture(&err_state, -1));
+ cl_assert(git_error_last() != NULL);
+ cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
+ cl_assert(strcmp("no error", git_error_last()->message) == 0);
git_error_set(99, "Bar: %s", "foo");
- git_error_state_free(&err_state);
-
- cl_assert_equal_i(99, git_error_last()->klass);
- cl_assert_equal_s("Bar: foo", git_error_last()->message);
+ git_error_restore(last_error);
- git_error_state_restore(&err_state);
-
- cl_assert(git_error_last() == NULL);
+ cl_assert(git_error_last()->klass == 42);
+ cl_assert(strcmp("Foo: bar", git_error_last()->message) == 0);
}
void test_errors__restore_oom(void)
{
- git_error_state err_state = {0};
+ git_error *last_error;
const git_error *oom_error = NULL;
git_error_clear();
@@ -141,15 +130,18 @@ void test_errors__restore_oom(void)
git_error_set_oom(); /* internal fn */
oom_error = git_error_last();
cl_assert(oom_error);
+ cl_assert(oom_error->klass == GIT_ERROR_NOMEMORY);
- cl_assert_equal_i(-1, git_error_state_capture(&err_state, -1));
-
- cl_assert(git_error_last() == NULL);
- cl_assert_equal_i(GIT_ERROR_NOMEMORY, err_state.error_msg.klass);
- cl_assert_equal_s("Out of memory", err_state.error_msg.message);
+ cl_assert(git_error_save(&last_error) == 0);
+ cl_assert(last_error->klass == GIT_ERROR_NOMEMORY);
+ cl_assert(strcmp("Out of memory", last_error->message) == 0);
- git_error_state_restore(&err_state);
+ git_error_clear();
+ cl_assert(git_error_last() != NULL);
+ cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
+ cl_assert(strcmp("no error", git_error_last()->message) == 0);
+ git_error_restore(last_error);
cl_assert(git_error_last()->klass == GIT_ERROR_NOMEMORY);
cl_assert_(git_error_last() == oom_error, "static oom error not restored");
@@ -204,11 +196,15 @@ void test_errors__integer_overflow_sets_oom(void)
git_error_clear();
cl_assert(!GIT_ADD_SIZET_OVERFLOW(&out, SIZE_MAX-1, 1));
- cl_assert_equal_p(NULL, git_error_last());
+ cl_assert(git_error_last() != NULL);
+ cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
+ cl_assert(strcmp(git_error_last()->message, "no error") == 0);
git_error_clear();
cl_assert(!GIT_ADD_SIZET_OVERFLOW(&out, 42, 69));
- cl_assert_equal_p(NULL, git_error_last());
+ cl_assert(git_error_last() != NULL);
+ cl_assert(git_error_last()->klass == GIT_ERROR_NONE);
+ cl_assert(strcmp(git_error_last()->message, "no error") == 0);
git_error_clear();
cl_assert(GIT_ADD_SIZET_OVERFLOW(&out, SIZE_MAX, SIZE_MAX));
diff --git a/tests/util/path.c b/tests/util/path.c
deleted file mode 100644
index 02ec42f..0000000
--- a/tests/util/path.c
+++ /dev/null
@@ -1,768 +0,0 @@
-#include "clar_libgit2.h"
-#include "futils.h"
-#include "fs_path.h"
-
-#ifndef GIT_WIN32
-# include <unistd.h>
-#endif
-
-static char *path_save;
-
-void test_path__initialize(void)
-{
- path_save = cl_getenv("PATH");
-}
-
-void test_path__cleanup(void)
-{
- cl_setenv("PATH", path_save);
- git__free(path_save);
- path_save = NULL;
-}
-
-static void
-check_dirname(const char *A, const char *B)
-{
- git_str dir = GIT_STR_INIT;
- char *dir2;
-
- cl_assert(git_fs_path_dirname_r(&dir, A) >= 0);
- cl_assert_equal_s(B, dir.ptr);
- git_str_dispose(&dir);
-
- cl_assert((dir2 = git_fs_path_dirname(A)) != NULL);
- cl_assert_equal_s(B, dir2);
- git__free(dir2);
-}
-
-static void
-check_basename(const char *A, const char *B)
-{
- git_str base = GIT_STR_INIT;
- char *base2;
-
- cl_assert(git_fs_path_basename_r(&base, A) >= 0);
- cl_assert_equal_s(B, base.ptr);
- git_str_dispose(&base);
-
- cl_assert((base2 = git_fs_path_basename(A)) != NULL);
- cl_assert_equal_s(B, base2);
- git__free(base2);
-}
-
-static void
-check_joinpath(const char *path_a, const char *path_b, const char *expected_path)
-{
- git_str joined_path = GIT_STR_INIT;
-
- cl_git_pass(git_str_joinpath(&joined_path, path_a, path_b));
- cl_assert_equal_s(expected_path, joined_path.ptr);
-
- git_str_dispose(&joined_path);
-}
-
-static void
-check_joinpath_n(
- const char *path_a,
- const char *path_b,
- const char *path_c,
- const char *path_d,
- const char *expected_path)
-{
- git_str joined_path = GIT_STR_INIT;
-
- cl_git_pass(git_str_join_n(&joined_path, '/', 4,
- path_a, path_b, path_c, path_d));
- cl_assert_equal_s(expected_path, joined_path.ptr);
-
- git_str_dispose(&joined_path);
-}
-
-static void check_setenv(const char* name, const char* value)
-{
- char* check;
-
- cl_git_pass(cl_setenv(name, value));
- check = cl_getenv(name);
-
- if (value)
- cl_assert_equal_s(value, check);
- else
- cl_assert(check == NULL);
-
- git__free(check);
-}
-
-/* get the dirname of a path */
-void test_path__00_dirname(void)
-{
- check_dirname(NULL, ".");
- check_dirname("", ".");
- check_dirname("a", ".");
- check_dirname("/", "/");
- check_dirname("/usr", "/");
- check_dirname("/usr/", "/");
- check_dirname("/usr/lib", "/usr");
- check_dirname("/usr/lib/", "/usr");
- check_dirname("/usr/lib//", "/usr");
- check_dirname("usr/lib", "usr");
- check_dirname("usr/lib/", "usr");
- check_dirname("usr/lib//", "usr");
- check_dirname(".git/", ".");
-
- check_dirname(REP16("/abc"), REP15("/abc"));
-
-#ifdef GIT_WIN32
- check_dirname("C:/", "C:/");
- check_dirname("C:", "C:/");
- check_dirname("C:/path/", "C:/");
- check_dirname("C:/path", "C:/");
- check_dirname("//computername/", "//computername/");
- check_dirname("//computername", "//computername/");
- check_dirname("//computername/path/", "//computername/");
- check_dirname("//computername/path", "//computername/");
- check_dirname("//computername/sub/path/", "//computername/sub");
- check_dirname("//computername/sub/path", "//computername/sub");
-#endif
-}
-
-/* get the base name of a path */
-void test_path__01_basename(void)
-{
- check_basename(NULL, ".");
- check_basename("", ".");
- check_basename("a", "a");
- check_basename("/", "/");
- check_basename("/usr", "usr");
- check_basename("/usr/", "usr");
- check_basename("/usr/lib", "lib");
- check_basename("/usr/lib//", "lib");
- check_basename("usr/lib", "lib");
-
- check_basename(REP16("/abc"), "abc");
- check_basename(REP1024("/abc"), "abc");
-}
-
-/* properly join path components */
-void test_path__05_joins(void)
-{
- check_joinpath("", "", "");
- check_joinpath("", "a", "a");
- check_joinpath("", "/a", "/a");
- check_joinpath("a", "", "a/");
- check_joinpath("a", "/", "a/");
- check_joinpath("a", "b", "a/b");
- check_joinpath("/", "a", "/a");
- check_joinpath("/", "", "/");
- check_joinpath("/a", "/b", "/a/b");
- check_joinpath("/a", "/b/", "/a/b/");
- check_joinpath("/a/", "b/", "/a/b/");
- check_joinpath("/a/", "/b/", "/a/b/");
-
- check_joinpath("/abcd", "/defg", "/abcd/defg");
- check_joinpath("/abcd", "/defg/", "/abcd/defg/");
- check_joinpath("/abcd/", "defg/", "/abcd/defg/");
- check_joinpath("/abcd/", "/defg/", "/abcd/defg/");
-
- check_joinpath("/abcdefgh", "/12345678", "/abcdefgh/12345678");
- check_joinpath("/abcdefgh", "/12345678/", "/abcdefgh/12345678/");
- check_joinpath("/abcdefgh/", "12345678/", "/abcdefgh/12345678/");
-
- check_joinpath(REP1024("aaaa"), "", REP1024("aaaa") "/");
- check_joinpath(REP1024("aaaa/"), "", REP1024("aaaa/"));
- check_joinpath(REP1024("/aaaa"), "", REP1024("/aaaa") "/");
-
- check_joinpath(REP1024("aaaa"), REP1024("bbbb"),
- REP1024("aaaa") "/" REP1024("bbbb"));
- check_joinpath(REP1024("/aaaa"), REP1024("/bbbb"),
- REP1024("/aaaa") REP1024("/bbbb"));
-}
-
-/* properly join path components for more than one path */
-void test_path__06_long_joins(void)
-{
- check_joinpath_n("", "", "", "", "");
- check_joinpath_n("", "a", "", "", "a/");
- check_joinpath_n("a", "", "", "", "a/");
- check_joinpath_n("", "", "", "a", "a");
- check_joinpath_n("a", "b", "", "/c/d/", "a/b/c/d/");
- check_joinpath_n("a", "b", "", "/c/d", "a/b/c/d");
- check_joinpath_n("abcd", "efgh", "ijkl", "mnop", "abcd/efgh/ijkl/mnop");
- check_joinpath_n("abcd/", "efgh/", "ijkl/", "mnop/", "abcd/efgh/ijkl/mnop/");
- check_joinpath_n("/abcd/", "/efgh/", "/ijkl/", "/mnop/", "/abcd/efgh/ijkl/mnop/");
-
- check_joinpath_n(REP1024("a"), REP1024("b"), REP1024("c"), REP1024("d"),
- REP1024("a") "/" REP1024("b") "/"
- REP1024("c") "/" REP1024("d"));
- check_joinpath_n(REP1024("/a"), REP1024("/b"), REP1024("/c"), REP1024("/d"),
- REP1024("/a") REP1024("/b")
- REP1024("/c") REP1024("/d"));
-}
-
-
-static void
-check_path_to_dir(
- const char* path,
- const char* expected)
-{
- git_str tgt = GIT_STR_INIT;
-
- git_str_sets(&tgt, path);
- cl_git_pass(git_fs_path_to_dir(&tgt));
- cl_assert_equal_s(expected, tgt.ptr);
-
- git_str_dispose(&tgt);
-}
-
-static void
-check_string_to_dir(
- const char* path,
- size_t maxlen,
- const char* expected)
-{
- size_t len = strlen(path);
- char *buf = git__malloc(len + 2);
- cl_assert(buf);
-
- strncpy(buf, path, len + 2);
-
- git_fs_path_string_to_dir(buf, maxlen);
-
- cl_assert_equal_s(expected, buf);
-
- git__free(buf);
-}
-
-/* convert paths to dirs */
-void test_path__07_path_to_dir(void)
-{
- check_path_to_dir("", "");
- check_path_to_dir(".", "./");
- check_path_to_dir("./", "./");
- check_path_to_dir("a/", "a/");
- check_path_to_dir("ab", "ab/");
- /* make sure we try just under and just over an expansion that will
- * require a realloc
- */
- check_path_to_dir("abcdef", "abcdef/");
- check_path_to_dir("abcdefg", "abcdefg/");
- check_path_to_dir("abcdefgh", "abcdefgh/");
- check_path_to_dir("abcdefghi", "abcdefghi/");
- check_path_to_dir(REP1024("abcd") "/", REP1024("abcd") "/");
- check_path_to_dir(REP1024("abcd"), REP1024("abcd") "/");
-
- check_string_to_dir("", 1, "");
- check_string_to_dir(".", 1, ".");
- check_string_to_dir(".", 2, "./");
- check_string_to_dir(".", 3, "./");
- check_string_to_dir("abcd", 3, "abcd");
- check_string_to_dir("abcd", 4, "abcd");
- check_string_to_dir("abcd", 5, "abcd/");
- check_string_to_dir("abcd", 6, "abcd/");
-}
-
-/* join path to itself */
-void test_path__08_self_join(void)
-{
- git_str path = GIT_STR_INIT;
- size_t asize = 0;
-
- asize = path.asize;
- cl_git_pass(git_str_sets(&path, "/foo"));
- cl_assert_equal_s(path.ptr, "/foo");
- cl_assert(asize < path.asize);
-
- asize = path.asize;
- cl_git_pass(git_str_joinpath(&path, path.ptr, "this is a new string"));
- cl_assert_equal_s(path.ptr, "/foo/this is a new string");
- cl_assert(asize < path.asize);
-
- asize = path.asize;
- cl_git_pass(git_str_joinpath(&path, path.ptr, "/grow the buffer, grow the buffer, grow the buffer"));
- cl_assert_equal_s(path.ptr, "/foo/this is a new string/grow the buffer, grow the buffer, grow the buffer");
- cl_assert(asize < path.asize);
-
- git_str_dispose(&path);
- cl_git_pass(git_str_sets(&path, "/foo/bar"));
-
- cl_git_pass(git_str_joinpath(&path, path.ptr + 4, "baz"));
- cl_assert_equal_s(path.ptr, "/bar/baz");
-
- asize = path.asize;
- cl_git_pass(git_str_joinpath(&path, path.ptr + 4, "somethinglongenoughtorealloc"));
- cl_assert_equal_s(path.ptr, "/baz/somethinglongenoughtorealloc");
- cl_assert(asize < path.asize);
-
- git_str_dispose(&path);
-}
-
-static void check_percent_decoding(const char *expected_result, const char *input)
-{
- git_str buf = GIT_STR_INIT;
-
- cl_git_pass(git__percent_decode(&buf, input));
- cl_assert_equal_s(expected_result, git_str_cstr(&buf));
-
- git_str_dispose(&buf);
-}
-
-void test_path__09_percent_decode(void)
-{
- check_percent_decoding("abcd", "abcd");
- check_percent_decoding("a2%", "a2%");
- check_percent_decoding("a2%3", "a2%3");
- check_percent_decoding("a2%%3", "a2%%3");
- check_percent_decoding("a2%3z", "a2%3z");
- check_percent_decoding("a,", "a%2c");
- check_percent_decoding("a21", "a2%31");
- check_percent_decoding("a2%1", "a2%%31");
- check_percent_decoding("a bc ", "a%20bc%20");
- check_percent_decoding("Vicent Mart" "\355", "Vicent%20Mart%ED");
-}
-
-static void check_fromurl(const char *expected_result, const char *input, int should_fail)
-{
- git_str buf = GIT_STR_INIT;
-
- assert(should_fail || expected_result);
-
- if (!should_fail) {
- cl_git_pass(git_fs_path_fromurl(&buf, input));
- cl_assert_equal_s(expected_result, git_str_cstr(&buf));
- } else
- cl_git_fail(git_fs_path_fromurl(&buf, input));
-
- git_str_dispose(&buf);
-}
-
-#ifdef GIT_WIN32
-#define ABS_PATH_MARKER ""
-#else
-#define ABS_PATH_MARKER "/"
-#endif
-
-void test_path__10_fromurl(void)
-{
- /* Failing cases */
- check_fromurl(NULL, "a", 1);
- check_fromurl(NULL, "http:///c:/Temp%20folder/note.txt", 1);
- check_fromurl(NULL, "file://c:/Temp%20folder/note.txt", 1);
- check_fromurl(NULL, "file:////c:/Temp%20folder/note.txt", 1);
- check_fromurl(NULL, "file:///", 1);
- check_fromurl(NULL, "file:////", 1);
- check_fromurl(NULL, "file://servername/c:/Temp%20folder/note.txt", 1);
-
- /* Passing cases */
- check_fromurl(ABS_PATH_MARKER "c:/Temp folder/note.txt", "file:///c:/Temp%20folder/note.txt", 0);
- check_fromurl(ABS_PATH_MARKER "c:/Temp folder/note.txt", "file://localhost/c:/Temp%20folder/note.txt", 0);
- check_fromurl(ABS_PATH_MARKER "c:/Temp+folder/note.txt", "file:///c:/Temp+folder/note.txt", 0);
- check_fromurl(ABS_PATH_MARKER "a", "file:///a", 0);
-}
-
-typedef struct {
- int expect_idx;
- int cancel_after;
- char **expect;
-} check_walkup_info;
-
-#define CANCEL_VALUE 1234
-
-static int check_one_walkup_step(void *ref, const char *path)
-{
- check_walkup_info *info = (check_walkup_info *)ref;
-
- if (!info->cancel_after) {
- cl_assert_equal_s(info->expect[info->expect_idx], "[CANCEL]");
- return CANCEL_VALUE;
- }
- info->cancel_after--;
-
- cl_assert(info->expect[info->expect_idx] != NULL);
- cl_assert_equal_s(info->expect[info->expect_idx], path);
- info->expect_idx++;
-
- return 0;
-}
-
-void test_path__11_walkup(void)
-{
- git_str p = GIT_STR_INIT;
-
- char *expect[] = {
- /* 1 */ "/a/b/c/d/e/", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
- /* 2 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
- /* 3 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
- /* 4 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
- /* 5 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", NULL,
- /* 6 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", NULL,
- /* 7 */ "this_is_a_path", "", NULL,
- /* 8 */ "this_is_a_path/", "", NULL,
- /* 9 */ "///a///b///c///d///e///", "///a///b///c///d///", "///a///b///c///", "///a///b///", "///a///", "///", NULL,
- /* 10 */ "a/b/c/", "a/b/", "a/", "", NULL,
- /* 11 */ "a/b/c", "a/b/", "a/", "", NULL,
- /* 12 */ "a/b/c/", "a/b/", "a/", NULL,
- /* 13 */ "", NULL,
- /* 14 */ "/", NULL,
- /* 15 */ NULL
- };
-
- char *root[] = {
- /* 1 */ NULL,
- /* 2 */ NULL,
- /* 3 */ "/",
- /* 4 */ "",
- /* 5 */ "/a/b",
- /* 6 */ "/a/b/",
- /* 7 */ NULL,
- /* 8 */ NULL,
- /* 9 */ NULL,
- /* 10 */ NULL,
- /* 11 */ NULL,
- /* 12 */ "a/",
- /* 13 */ NULL,
- /* 14 */ NULL,
- };
-
- int i, j;
- check_walkup_info info;
-
- info.expect = expect;
- info.cancel_after = -1;
-
- for (i = 0, j = 0; expect[i] != NULL; i++, j++) {
-
- git_str_sets(&p, expect[i]);
-
- info.expect_idx = i;
- cl_git_pass(
- git_fs_path_walk_up(&p, root[j], check_one_walkup_step, &info)
- );
-
- cl_assert_equal_s(p.ptr, expect[i]);
- cl_assert(expect[info.expect_idx] == NULL);
- i = info.expect_idx;
- }
-
- git_str_dispose(&p);
-}
-
-void test_path__11a_walkup_cancel(void)
-{
- git_str p = GIT_STR_INIT;
- int cancel[] = { 3, 2, 1, 0 };
- char *expect[] = {
- "/a/b/c/d/e/", "/a/b/c/d/", "/a/b/c/", "[CANCEL]", NULL,
- "/a/b/c/d/e", "/a/b/c/d/", "[CANCEL]", NULL,
- "/a/b/c/d/e", "[CANCEL]", NULL,
- "[CANCEL]", NULL,
- NULL
- };
- char *root[] = { NULL, NULL, "/", "", NULL };
- int i, j;
- check_walkup_info info;
-
- info.expect = expect;
-
- for (i = 0, j = 0; expect[i] != NULL; i++, j++) {
-
- git_str_sets(&p, expect[i]);
-
- info.cancel_after = cancel[j];
- info.expect_idx = i;
-
- cl_assert_equal_i(
- CANCEL_VALUE,
- git_fs_path_walk_up(&p, root[j], check_one_walkup_step, &info)
- );
-
- /* skip to next run of expectations */
- while (expect[i] != NULL) i++;
- }
-
- git_str_dispose(&p);
-}
-
-void test_path__12_offset_to_path_root(void)
-{
- cl_assert(git_fs_path_root("non/rooted/path") == -1);
- cl_assert(git_fs_path_root("/rooted/path") == 0);
-
-#ifdef GIT_WIN32
- /* Windows specific tests */
- cl_assert(git_fs_path_root("C:non/rooted/path") == -1);
- cl_assert(git_fs_path_root("C:/rooted/path") == 2);
- cl_assert(git_fs_path_root("//computername/sharefolder/resource") == 14);
- cl_assert(git_fs_path_root("//computername/sharefolder") == 14);
- cl_assert(git_fs_path_root("//computername") == -1);
-#endif
-}
-
-#define NON_EXISTING_FILEPATH "i_hope_i_do_not_exist"
-
-void test_path__13_cannot_prettify_a_non_existing_file(void)
-{
- git_str p = GIT_STR_INIT;
-
- cl_assert_equal_b(git_fs_path_exists(NON_EXISTING_FILEPATH), false);
- cl_assert_equal_i(GIT_ENOTFOUND, git_fs_path_prettify(&p, NON_EXISTING_FILEPATH, NULL));
- cl_assert_equal_i(GIT_ENOTFOUND, git_fs_path_prettify(&p, NON_EXISTING_FILEPATH "/so-do-i", NULL));
-
- git_str_dispose(&p);
-}
-
-void test_path__14_apply_relative(void)
-{
- git_str p = GIT_STR_INIT;
-
- cl_git_pass(git_str_sets(&p, "/this/is/a/base"));
-
- cl_git_pass(git_fs_path_apply_relative(&p, "../test"));
- cl_assert_equal_s("/this/is/a/test", p.ptr);
-
- cl_git_pass(git_fs_path_apply_relative(&p, "../../the/./end"));
- cl_assert_equal_s("/this/is/the/end", p.ptr);
-
- cl_git_pass(git_fs_path_apply_relative(&p, "./of/this/../the/string"));
- cl_assert_equal_s("/this/is/the/end/of/the/string", p.ptr);
-
- cl_git_pass(git_fs_path_apply_relative(&p, "../../../../../.."));
- cl_assert_equal_s("/this/", p.ptr);
-
- cl_git_pass(git_fs_path_apply_relative(&p, "../"));
- cl_assert_equal_s("/", p.ptr);
-
- cl_git_fail(git_fs_path_apply_relative(&p, "../../.."));
-
-
- cl_git_pass(git_str_sets(&p, "d:/another/test"));
-
- cl_git_pass(git_fs_path_apply_relative(&p, "../.."));
- cl_assert_equal_s("d:/", p.ptr);
-
- cl_git_pass(git_fs_path_apply_relative(&p, "from/here/to/../and/./back/."));
- cl_assert_equal_s("d:/from/here/and/back/", p.ptr);
-
-
- cl_git_pass(git_str_sets(&p, "https://my.url.com/test.git"));
-
- cl_git_pass(git_fs_path_apply_relative(&p, "../another.git"));
- cl_assert_equal_s("https://my.url.com/another.git", p.ptr);
-
- cl_git_pass(git_fs_path_apply_relative(&p, "../full/path/url.patch"));
- cl_assert_equal_s("https://my.url.com/full/path/url.patch", p.ptr);
-
- cl_git_pass(git_fs_path_apply_relative(&p, ".."));
- cl_assert_equal_s("https://my.url.com/full/path/", p.ptr);
-
- cl_git_pass(git_fs_path_apply_relative(&p, "../../../"));
- cl_assert_equal_s("https://", p.ptr);
-
-
- cl_git_pass(git_str_sets(&p, "../../this/is/relative"));
-
- cl_git_pass(git_fs_path_apply_relative(&p, "../../preserves/the/prefix"));
- cl_assert_equal_s("../../this/preserves/the/prefix", p.ptr);
-
- cl_git_pass(git_fs_path_apply_relative(&p, "../../../../that"));
- cl_assert_equal_s("../../that", p.ptr);
-
- cl_git_pass(git_fs_path_apply_relative(&p, "../there"));
- cl_assert_equal_s("../../there", p.ptr);
- git_str_dispose(&p);
-}
-
-static void assert_resolve_relative(
- git_str *buf, const char *expected, const char *path)
-{
- cl_git_pass(git_str_sets(buf, path));
- cl_git_pass(git_fs_path_resolve_relative(buf, 0));
- cl_assert_equal_s(expected, buf->ptr);
-}
-
-void test_path__15_resolve_relative(void)
-{
- git_str buf = GIT_STR_INIT;
-
- assert_resolve_relative(&buf, "", "");
- assert_resolve_relative(&buf, "", ".");
- assert_resolve_relative(&buf, "", "./");
- assert_resolve_relative(&buf, "..", "..");
- assert_resolve_relative(&buf, "../", "../");
- assert_resolve_relative(&buf, "..", "./..");
- assert_resolve_relative(&buf, "../", "./../");
- assert_resolve_relative(&buf, "../", "../.");
- assert_resolve_relative(&buf, "../", ".././");
- assert_resolve_relative(&buf, "../..", "../..");
- assert_resolve_relative(&buf, "../../", "../../");
-
- assert_resolve_relative(&buf, "/", "/");
- assert_resolve_relative(&buf, "/", "/.");
-
- assert_resolve_relative(&buf, "", "a/..");
- assert_resolve_relative(&buf, "", "a/../");
- assert_resolve_relative(&buf, "", "a/../.");
-
- assert_resolve_relative(&buf, "/a", "/a");
- assert_resolve_relative(&buf, "/a/", "/a/.");
- assert_resolve_relative(&buf, "/", "/a/../");
- assert_resolve_relative(&buf, "/", "/a/../.");
- assert_resolve_relative(&buf, "/", "/a/.././");
-
- assert_resolve_relative(&buf, "a", "a");
- assert_resolve_relative(&buf, "a/", "a/");
- assert_resolve_relative(&buf, "a/", "a/.");
- assert_resolve_relative(&buf, "a/", "a/./");
-
- assert_resolve_relative(&buf, "a/b", "a//b");
- assert_resolve_relative(&buf, "a/b/c", "a/b/c");
- assert_resolve_relative(&buf, "b/c", "./b/c");
- assert_resolve_relative(&buf, "a/c", "a/./c");
- assert_resolve_relative(&buf, "a/b/", "a/b/.");
-
- assert_resolve_relative(&buf, "/a/b/c", "///a/b/c");
- assert_resolve_relative(&buf, "/", "////");
- assert_resolve_relative(&buf, "/a", "///a");
- assert_resolve_relative(&buf, "/", "///.");
- assert_resolve_relative(&buf, "/", "///a/..");
-
- assert_resolve_relative(&buf, "../../path", "../../test//../././path");
- assert_resolve_relative(&buf, "../d", "a/b/../../../c/../d");
-
- cl_git_pass(git_str_sets(&buf, "/.."));
- cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
-
- cl_git_pass(git_str_sets(&buf, "/./.."));
- cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
-
- cl_git_pass(git_str_sets(&buf, "/.//.."));
- cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
-
- cl_git_pass(git_str_sets(&buf, "/../."));
- cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
-
- cl_git_pass(git_str_sets(&buf, "/../.././../a"));
- cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
-
- cl_git_pass(git_str_sets(&buf, "////.."));
- cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
-
- /* things that start with Windows network paths */
-#ifdef GIT_WIN32
- assert_resolve_relative(&buf, "//a/b/c", "//a/b/c");
- assert_resolve_relative(&buf, "//a/", "//a/b/..");
- assert_resolve_relative(&buf, "//a/b/c", "//a/Q/../b/x/y/../../c");
-
- cl_git_pass(git_str_sets(&buf, "//a/b/../.."));
- cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
-#else
- assert_resolve_relative(&buf, "/a/b/c", "//a/b/c");
- assert_resolve_relative(&buf, "/a/", "//a/b/..");
- assert_resolve_relative(&buf, "/a/b/c", "//a/Q/../b/x/y/../../c");
- assert_resolve_relative(&buf, "/", "//a/b/../..");
-#endif
-
- git_str_dispose(&buf);
-}
-
-#define assert_common_dirlen(i, p, q) \
- cl_assert_equal_i((i), git_fs_path_common_dirlen((p), (q)));
-
-void test_path__16_resolve_relative(void)
-{
- assert_common_dirlen(0, "", "");
- assert_common_dirlen(0, "", "bar.txt");
- assert_common_dirlen(0, "foo.txt", "bar.txt");
- assert_common_dirlen(0, "foo.txt", "");
- assert_common_dirlen(0, "foo/bar.txt", "bar/foo.txt");
- assert_common_dirlen(0, "foo/bar.txt", "../foo.txt");
-
- assert_common_dirlen(1, "/one.txt", "/two.txt");
- assert_common_dirlen(4, "foo/one.txt", "foo/two.txt");
- assert_common_dirlen(5, "/foo/one.txt", "/foo/two.txt");
-
- assert_common_dirlen(6, "a/b/c/foo.txt", "a/b/c/d/e/bar.txt");
- assert_common_dirlen(7, "/a/b/c/foo.txt", "/a/b/c/d/e/bar.txt");
-}
-
-static void fix_path(git_str *s)
-{
-#ifndef GIT_WIN32
- GIT_UNUSED(s);
-#else
- char* c;
-
- for (c = s->ptr; *c; c++) {
- if (*c == '/')
- *c = '\\';
- }
-#endif
-}
-
-void test_path__find_exe_in_path(void)
-{
- char *orig_path;
- git_str sandbox_path = GIT_STR_INIT;
- git_str new_path = GIT_STR_INIT, full_path = GIT_STR_INIT,
- dummy_path = GIT_STR_INIT;
-
-#ifdef GIT_WIN32
- static const char *bogus_path_1 = "c:\\does\\not\\exist\\";
- static const char *bogus_path_2 = "e:\\non\\existent";
-#else
- static const char *bogus_path_1 = "/this/path/does/not/exist/";
- static const char *bogus_path_2 = "/non/existent";
-#endif
-
- orig_path = cl_getenv("PATH");
-
- git_str_puts(&sandbox_path, clar_sandbox_path());
- git_str_joinpath(&dummy_path, sandbox_path.ptr, "dummmmmmmy_libgit2_file");
- cl_git_rewritefile(dummy_path.ptr, "this is a dummy file");
-
- fix_path(&sandbox_path);
- fix_path(&dummy_path);
-
- cl_git_pass(git_str_printf(&new_path, "%s%c%s%c%s%c%s",
- bogus_path_1, GIT_PATH_LIST_SEPARATOR,
- orig_path, GIT_PATH_LIST_SEPARATOR,
- sandbox_path.ptr, GIT_PATH_LIST_SEPARATOR,
- bogus_path_2));
-
- check_setenv("PATH", new_path.ptr);
-
- cl_git_fail_with(GIT_ENOTFOUND, git_fs_path_find_executable(&full_path, "this_file_does_not_exist"));
- cl_git_pass(git_fs_path_find_executable(&full_path, "dummmmmmmy_libgit2_file"));
-
- cl_assert_equal_s(full_path.ptr, dummy_path.ptr);
-
- git_str_dispose(&full_path);
- git_str_dispose(&new_path);
- git_str_dispose(&dummy_path);
- git_str_dispose(&sandbox_path);
- git__free(orig_path);
-}
-
-void test_path__validate_current_user_ownership(void)
-{
- bool is_cur;
-
- cl_must_pass(p_mkdir("testdir", 0777));
- cl_git_pass(git_fs_path_owner_is_current_user(&is_cur, "testdir"));
- cl_assert_equal_i(is_cur, 1);
-
- cl_git_rewritefile("testfile", "This is a test file.");
- cl_git_pass(git_fs_path_owner_is_current_user(&is_cur, "testfile"));
- cl_assert_equal_i(is_cur, 1);
-
-#ifdef GIT_WIN32
- cl_git_pass(git_fs_path_owner_is_current_user(&is_cur, "C:\\"));
- cl_assert_equal_i(is_cur, 0);
-
- cl_git_fail(git_fs_path_owner_is_current_user(&is_cur, "c:\\path\\does\\not\\exist"));
-#else
- cl_git_pass(git_fs_path_owner_is_current_user(&is_cur, "/"));
- cl_assert_equal_i(is_cur, (geteuid() == 0));
-
- cl_git_fail(git_fs_path_owner_is_current_user(&is_cur, "/path/does/not/exist"));
-#endif
-}
diff --git a/tests/util/path/core.c b/tests/util/path/core.c
index f30f6c0..d1935a8 100644
--- a/tests/util/path/core.c
+++ b/tests/util/path/core.c
@@ -1,6 +1,784 @@
#include "clar_libgit2.h"
+#include "futils.h"
#include "fs_path.h"
+#ifndef GIT_WIN32
+# include <unistd.h>
+#endif
+
+static char *path_save;
+
+void test_path_core__initialize(void)
+{
+ path_save = cl_getenv("PATH");
+}
+
+void test_path_core__cleanup(void)
+{
+ cl_setenv("PATH", path_save);
+ git__free(path_save);
+ path_save = NULL;
+}
+
+static void
+check_dirname(const char *A, const char *B)
+{
+ git_str dir = GIT_STR_INIT;
+ char *dir2;
+
+ cl_assert(git_fs_path_dirname_r(&dir, A) >= 0);
+ cl_assert_equal_s(B, dir.ptr);
+ git_str_dispose(&dir);
+
+ cl_assert((dir2 = git_fs_path_dirname(A)) != NULL);
+ cl_assert_equal_s(B, dir2);
+ git__free(dir2);
+}
+
+static void
+check_basename(const char *A, const char *B)
+{
+ git_str base = GIT_STR_INIT;
+ char *base2;
+
+ cl_assert(git_fs_path_basename_r(&base, A) >= 0);
+ cl_assert_equal_s(B, base.ptr);
+ git_str_dispose(&base);
+
+ cl_assert((base2 = git_fs_path_basename(A)) != NULL);
+ cl_assert_equal_s(B, base2);
+ git__free(base2);
+}
+
+static void
+check_joinpath(const char *path_a, const char *path_b, const char *expected_path)
+{
+ git_str joined_path = GIT_STR_INIT;
+
+ cl_git_pass(git_str_joinpath(&joined_path, path_a, path_b));
+ cl_assert_equal_s(expected_path, joined_path.ptr);
+
+ git_str_dispose(&joined_path);
+}
+
+static void
+check_joinpath_n(
+ const char *path_a,
+ const char *path_b,
+ const char *path_c,
+ const char *path_d,
+ const char *expected_path)
+{
+ git_str joined_path = GIT_STR_INIT;
+
+ cl_git_pass(git_str_join_n(&joined_path, '/', 4,
+ path_a, path_b, path_c, path_d));
+ cl_assert_equal_s(expected_path, joined_path.ptr);
+
+ git_str_dispose(&joined_path);
+}
+
+static void check_setenv(const char* name, const char* value)
+{
+ char* check;
+
+ cl_git_pass(cl_setenv(name, value));
+ check = cl_getenv(name);
+
+ if (value)
+ cl_assert_equal_s(value, check);
+ else
+ cl_assert(check == NULL);
+
+ git__free(check);
+}
+
+/* get the dirname of a path */
+void test_path_core__00_dirname(void)
+{
+ check_dirname(NULL, ".");
+ check_dirname("", ".");
+ check_dirname("a", ".");
+ check_dirname("/", "/");
+ check_dirname("/usr", "/");
+ check_dirname("/usr/", "/");
+ check_dirname("/usr/lib", "/usr");
+ check_dirname("/usr/lib/", "/usr");
+ check_dirname("/usr/lib//", "/usr");
+ check_dirname("usr/lib", "usr");
+ check_dirname("usr/lib/", "usr");
+ check_dirname("usr/lib//", "usr");
+ check_dirname(".git/", ".");
+
+ check_dirname(REP16("/abc"), REP15("/abc"));
+
+#ifdef GIT_WIN32
+ check_dirname("C:/", "C:/");
+ check_dirname("C:", "C:/");
+ check_dirname("C:/path/", "C:/");
+ check_dirname("C:/path", "C:/");
+ check_dirname("//computername/", "//computername/");
+ check_dirname("//computername", "//computername/");
+ check_dirname("//computername/path/", "//computername/");
+ check_dirname("//computername/path", "//computername/");
+ check_dirname("//computername/sub/path/", "//computername/sub");
+ check_dirname("//computername/sub/path", "//computername/sub");
+#endif
+}
+
+/* get the base name of a path */
+void test_path_core__01_basename(void)
+{
+ check_basename(NULL, ".");
+ check_basename("", ".");
+ check_basename("a", "a");
+ check_basename("/", "/");
+ check_basename("/usr", "usr");
+ check_basename("/usr/", "usr");
+ check_basename("/usr/lib", "lib");
+ check_basename("/usr/lib//", "lib");
+ check_basename("usr/lib", "lib");
+
+ check_basename(REP16("/abc"), "abc");
+ check_basename(REP1024("/abc"), "abc");
+}
+
+/* properly join path components */
+void test_path_core__05_joins(void)
+{
+ check_joinpath("", "", "");
+ check_joinpath("", "a", "a");
+ check_joinpath("", "/a", "/a");
+ check_joinpath("a", "", "a/");
+ check_joinpath("a", "/", "a/");
+ check_joinpath("a", "b", "a/b");
+ check_joinpath("/", "a", "/a");
+ check_joinpath("/", "", "/");
+ check_joinpath("/a", "/b", "/a/b");
+ check_joinpath("/a", "/b/", "/a/b/");
+ check_joinpath("/a/", "b/", "/a/b/");
+ check_joinpath("/a/", "/b/", "/a/b/");
+
+ check_joinpath("/abcd", "/defg", "/abcd/defg");
+ check_joinpath("/abcd", "/defg/", "/abcd/defg/");
+ check_joinpath("/abcd/", "defg/", "/abcd/defg/");
+ check_joinpath("/abcd/", "/defg/", "/abcd/defg/");
+
+ check_joinpath("/abcdefgh", "/12345678", "/abcdefgh/12345678");
+ check_joinpath("/abcdefgh", "/12345678/", "/abcdefgh/12345678/");
+ check_joinpath("/abcdefgh/", "12345678/", "/abcdefgh/12345678/");
+
+ check_joinpath(REP1024("aaaa"), "", REP1024("aaaa") "/");
+ check_joinpath(REP1024("aaaa/"), "", REP1024("aaaa/"));
+ check_joinpath(REP1024("/aaaa"), "", REP1024("/aaaa") "/");
+
+ check_joinpath(REP1024("aaaa"), REP1024("bbbb"),
+ REP1024("aaaa") "/" REP1024("bbbb"));
+ check_joinpath(REP1024("/aaaa"), REP1024("/bbbb"),
+ REP1024("/aaaa") REP1024("/bbbb"));
+}
+
+/* properly join path components for more than one path */
+void test_path_core__06_long_joins(void)
+{
+ check_joinpath_n("", "", "", "", "");
+ check_joinpath_n("", "a", "", "", "a/");
+ check_joinpath_n("a", "", "", "", "a/");
+ check_joinpath_n("", "", "", "a", "a");
+ check_joinpath_n("a", "b", "", "/c/d/", "a/b/c/d/");
+ check_joinpath_n("a", "b", "", "/c/d", "a/b/c/d");
+ check_joinpath_n("abcd", "efgh", "ijkl", "mnop", "abcd/efgh/ijkl/mnop");
+ check_joinpath_n("abcd/", "efgh/", "ijkl/", "mnop/", "abcd/efgh/ijkl/mnop/");
+ check_joinpath_n("/abcd/", "/efgh/", "/ijkl/", "/mnop/", "/abcd/efgh/ijkl/mnop/");
+
+ check_joinpath_n(REP1024("a"), REP1024("b"), REP1024("c"), REP1024("d"),
+ REP1024("a") "/" REP1024("b") "/"
+ REP1024("c") "/" REP1024("d"));
+ check_joinpath_n(REP1024("/a"), REP1024("/b"), REP1024("/c"), REP1024("/d"),
+ REP1024("/a") REP1024("/b")
+ REP1024("/c") REP1024("/d"));
+}
+
+
+static void
+check_path_to_dir(
+ const char* path,
+ const char* expected)
+{
+ git_str tgt = GIT_STR_INIT;
+
+ git_str_sets(&tgt, path);
+ cl_git_pass(git_fs_path_to_dir(&tgt));
+ cl_assert_equal_s(expected, tgt.ptr);
+
+ git_str_dispose(&tgt);
+}
+
+static void
+check_string_to_dir(
+ const char* path,
+ size_t maxlen,
+ const char* expected)
+{
+ size_t len = strlen(path);
+ char *buf = git__malloc(len + 2);
+ cl_assert(buf);
+
+ strncpy(buf, path, len + 2);
+
+ git_fs_path_string_to_dir(buf, maxlen);
+
+ cl_assert_equal_s(expected, buf);
+
+ git__free(buf);
+}
+
+/* convert paths to dirs */
+void test_path_core__07_path_to_dir(void)
+{
+ check_path_to_dir("", "");
+ check_path_to_dir(".", "./");
+ check_path_to_dir("./", "./");
+ check_path_to_dir("a/", "a/");
+ check_path_to_dir("ab", "ab/");
+ /* make sure we try just under and just over an expansion that will
+ * require a realloc
+ */
+ check_path_to_dir("abcdef", "abcdef/");
+ check_path_to_dir("abcdefg", "abcdefg/");
+ check_path_to_dir("abcdefgh", "abcdefgh/");
+ check_path_to_dir("abcdefghi", "abcdefghi/");
+ check_path_to_dir(REP1024("abcd") "/", REP1024("abcd") "/");
+ check_path_to_dir(REP1024("abcd"), REP1024("abcd") "/");
+
+ check_string_to_dir("", 1, "");
+ check_string_to_dir(".", 1, ".");
+ check_string_to_dir(".", 2, "./");
+ check_string_to_dir(".", 3, "./");
+ check_string_to_dir("abcd", 3, "abcd");
+ check_string_to_dir("abcd", 4, "abcd");
+ check_string_to_dir("abcd", 5, "abcd/");
+ check_string_to_dir("abcd", 6, "abcd/");
+}
+
+/* join path to itself */
+void test_path_core__08_self_join(void)
+{
+ git_str path = GIT_STR_INIT;
+ size_t asize = 0;
+
+ asize = path.asize;
+ cl_git_pass(git_str_sets(&path, "/foo"));
+ cl_assert_equal_s(path.ptr, "/foo");
+ cl_assert(asize < path.asize);
+
+ asize = path.asize;
+ cl_git_pass(git_str_joinpath(&path, path.ptr, "this is a new string"));
+ cl_assert_equal_s(path.ptr, "/foo/this is a new string");
+ cl_assert(asize < path.asize);
+
+ asize = path.asize;
+ cl_git_pass(git_str_joinpath(&path, path.ptr, "/grow the buffer, grow the buffer, grow the buffer"));
+ cl_assert_equal_s(path.ptr, "/foo/this is a new string/grow the buffer, grow the buffer, grow the buffer");
+ cl_assert(asize < path.asize);
+
+ git_str_dispose(&path);
+ cl_git_pass(git_str_sets(&path, "/foo/bar"));
+
+ cl_git_pass(git_str_joinpath(&path, path.ptr + 4, "baz"));
+ cl_assert_equal_s(path.ptr, "/bar/baz");
+
+ asize = path.asize;
+ cl_git_pass(git_str_joinpath(&path, path.ptr + 4, "somethinglongenoughtorealloc"));
+ cl_assert_equal_s(path.ptr, "/baz/somethinglongenoughtorealloc");
+ cl_assert(asize < path.asize);
+
+ git_str_dispose(&path);
+}
+
+static void check_percent_decoding(const char *expected_result, const char *input)
+{
+ git_str buf = GIT_STR_INIT;
+
+ cl_git_pass(git__percent_decode(&buf, input));
+ cl_assert_equal_s(expected_result, git_str_cstr(&buf));
+
+ git_str_dispose(&buf);
+}
+
+void test_path_core__09_percent_decode(void)
+{
+ check_percent_decoding("abcd", "abcd");
+ check_percent_decoding("a2%", "a2%");
+ check_percent_decoding("a2%3", "a2%3");
+ check_percent_decoding("a2%%3", "a2%%3");
+ check_percent_decoding("a2%3z", "a2%3z");
+ check_percent_decoding("a,", "a%2c");
+ check_percent_decoding("a21", "a2%31");
+ check_percent_decoding("a2%1", "a2%%31");
+ check_percent_decoding("a bc ", "a%20bc%20");
+ check_percent_decoding("Vicent Mart" "\355", "Vicent%20Mart%ED");
+}
+
+static void check_fromurl(const char *expected_result, const char *input, int should_fail)
+{
+ git_str buf = GIT_STR_INIT;
+
+ assert(should_fail || expected_result);
+
+ if (!should_fail) {
+ cl_git_pass(git_fs_path_fromurl(&buf, input));
+ cl_assert_equal_s(expected_result, git_str_cstr(&buf));
+ } else
+ cl_git_fail(git_fs_path_fromurl(&buf, input));
+
+ git_str_dispose(&buf);
+}
+
+#ifdef GIT_WIN32
+#define ABS_PATH_MARKER ""
+#else
+#define ABS_PATH_MARKER "/"
+#endif
+
+void test_path_core__10_fromurl(void)
+{
+ /* Failing cases */
+ check_fromurl(NULL, "a", 1);
+ check_fromurl(NULL, "http:///c:/Temp%20folder/note.txt", 1);
+ check_fromurl(NULL, "file://c:/Temp%20folder/note.txt", 1);
+ check_fromurl(NULL, "file:////c:/Temp%20folder/note.txt", 1);
+ check_fromurl(NULL, "file:///", 1);
+ check_fromurl(NULL, "file:////", 1);
+ check_fromurl(NULL, "file://servername/c:/Temp%20folder/note.txt", 1);
+
+ /* Passing cases */
+ check_fromurl(ABS_PATH_MARKER "c:/Temp folder/note.txt", "file:///c:/Temp%20folder/note.txt", 0);
+ check_fromurl(ABS_PATH_MARKER "c:/Temp folder/note.txt", "file://localhost/c:/Temp%20folder/note.txt", 0);
+ check_fromurl(ABS_PATH_MARKER "c:/Temp+folder/note.txt", "file:///c:/Temp+folder/note.txt", 0);
+ check_fromurl(ABS_PATH_MARKER "a", "file:///a", 0);
+}
+
+typedef struct {
+ int expect_idx;
+ int cancel_after;
+ char **expect;
+} check_walkup_info;
+
+#define CANCEL_VALUE 1234
+
+static int check_one_walkup_step(void *ref, const char *path)
+{
+ check_walkup_info *info = (check_walkup_info *)ref;
+
+ if (!info->cancel_after) {
+ cl_assert_equal_s(info->expect[info->expect_idx], "[CANCEL]");
+ return CANCEL_VALUE;
+ }
+ info->cancel_after--;
+
+ cl_assert(info->expect[info->expect_idx] != NULL);
+ cl_assert_equal_s(info->expect[info->expect_idx], path);
+ info->expect_idx++;
+
+ return 0;
+}
+
+void test_path_core__11_walkup(void)
+{
+ git_str p = GIT_STR_INIT;
+
+ char *expect[] = {
+ /* 1 */ "/a/b/c/d/e/", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
+ /* 2 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
+ /* 3 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
+ /* 4 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", "/a/", "/", NULL,
+ /* 5 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", NULL,
+ /* 6 */ "/a/b/c/d/e", "/a/b/c/d/", "/a/b/c/", "/a/b/", NULL,
+ /* 7 */ "this_is_a_path", "", NULL,
+ /* 8 */ "this_is_a_path/", "", NULL,
+ /* 9 */ "///a///b///c///d///e///", "///a///b///c///d///", "///a///b///c///", "///a///b///", "///a///", "///", NULL,
+ /* 10 */ "a/b/c/", "a/b/", "a/", "", NULL,
+ /* 11 */ "a/b/c", "a/b/", "a/", "", NULL,
+ /* 12 */ "a/b/c/", "a/b/", "a/", NULL,
+ /* 13 */ "", NULL,
+ /* 14 */ "/", NULL,
+ /* 15 */ NULL
+ };
+
+ char *root[] = {
+ /* 1 */ NULL,
+ /* 2 */ NULL,
+ /* 3 */ "/",
+ /* 4 */ "",
+ /* 5 */ "/a/b",
+ /* 6 */ "/a/b/",
+ /* 7 */ NULL,
+ /* 8 */ NULL,
+ /* 9 */ NULL,
+ /* 10 */ NULL,
+ /* 11 */ NULL,
+ /* 12 */ "a/",
+ /* 13 */ NULL,
+ /* 14 */ NULL,
+ };
+
+ int i, j;
+ check_walkup_info info;
+
+ info.expect = expect;
+ info.cancel_after = -1;
+
+ for (i = 0, j = 0; expect[i] != NULL; i++, j++) {
+
+ git_str_sets(&p, expect[i]);
+
+ info.expect_idx = i;
+ cl_git_pass(
+ git_fs_path_walk_up(&p, root[j], check_one_walkup_step, &info)
+ );
+
+ cl_assert_equal_s(p.ptr, expect[i]);
+ cl_assert(expect[info.expect_idx] == NULL);
+ i = info.expect_idx;
+ }
+
+ git_str_dispose(&p);
+}
+
+void test_path_core__11a_walkup_cancel(void)
+{
+ git_str p = GIT_STR_INIT;
+ int cancel[] = { 3, 2, 1, 0 };
+ char *expect[] = {
+ "/a/b/c/d/e/", "/a/b/c/d/", "/a/b/c/", "[CANCEL]", NULL,
+ "/a/b/c/d/e", "/a/b/c/d/", "[CANCEL]", NULL,
+ "/a/b/c/d/e", "[CANCEL]", NULL,
+ "[CANCEL]", NULL,
+ NULL
+ };
+ char *root[] = { NULL, NULL, "/", "", NULL };
+ int i, j;
+ check_walkup_info info;
+
+ info.expect = expect;
+
+ for (i = 0, j = 0; expect[i] != NULL; i++, j++) {
+
+ git_str_sets(&p, expect[i]);
+
+ info.cancel_after = cancel[j];
+ info.expect_idx = i;
+
+ cl_assert_equal_i(
+ CANCEL_VALUE,
+ git_fs_path_walk_up(&p, root[j], check_one_walkup_step, &info)
+ );
+
+ /* skip to next run of expectations */
+ while (expect[i] != NULL) i++;
+ }
+
+ git_str_dispose(&p);
+}
+
+void test_path_core__12_offset_to_path_root(void)
+{
+ cl_assert(git_fs_path_root("non/rooted/path") == -1);
+ cl_assert(git_fs_path_root("/rooted/path") == 0);
+
+#ifdef GIT_WIN32
+ /* Windows specific tests */
+ cl_assert(git_fs_path_root("C:non/rooted/path") == -1);
+ cl_assert(git_fs_path_root("C:/rooted/path") == 2);
+ cl_assert(git_fs_path_root("//computername/sharefolder/resource") == 14);
+ cl_assert(git_fs_path_root("//computername/sharefolder") == 14);
+ cl_assert(git_fs_path_root("//computername") == -1);
+#endif
+}
+
+#define NON_EXISTING_FILEPATH "i_hope_i_do_not_exist"
+
+void test_path_core__13_cannot_prettify_a_non_existing_file(void)
+{
+ git_str p = GIT_STR_INIT;
+
+ cl_assert_equal_b(git_fs_path_exists(NON_EXISTING_FILEPATH), false);
+ cl_assert_equal_i(GIT_ENOTFOUND, git_fs_path_prettify(&p, NON_EXISTING_FILEPATH, NULL));
+ cl_assert_equal_i(GIT_ENOTFOUND, git_fs_path_prettify(&p, NON_EXISTING_FILEPATH "/so-do-i", NULL));
+
+ git_str_dispose(&p);
+}
+
+void test_path_core__14_apply_relative(void)
+{
+ git_str p = GIT_STR_INIT;
+
+ cl_git_pass(git_str_sets(&p, "/this/is/a/base"));
+
+ cl_git_pass(git_fs_path_apply_relative(&p, "../test"));
+ cl_assert_equal_s("/this/is/a/test", p.ptr);
+
+ cl_git_pass(git_fs_path_apply_relative(&p, "../../the/./end"));
+ cl_assert_equal_s("/this/is/the/end", p.ptr);
+
+ cl_git_pass(git_fs_path_apply_relative(&p, "./of/this/../the/string"));
+ cl_assert_equal_s("/this/is/the/end/of/the/string", p.ptr);
+
+ cl_git_pass(git_fs_path_apply_relative(&p, "../../../../../.."));
+ cl_assert_equal_s("/this/", p.ptr);
+
+ cl_git_pass(git_fs_path_apply_relative(&p, "../"));
+ cl_assert_equal_s("/", p.ptr);
+
+ cl_git_fail(git_fs_path_apply_relative(&p, "../../.."));
+
+
+ cl_git_pass(git_str_sets(&p, "d:/another/test"));
+
+ cl_git_pass(git_fs_path_apply_relative(&p, "../.."));
+ cl_assert_equal_s("d:/", p.ptr);
+
+ cl_git_pass(git_fs_path_apply_relative(&p, "from/here/to/../and/./back/."));
+ cl_assert_equal_s("d:/from/here/and/back/", p.ptr);
+
+
+ cl_git_pass(git_str_sets(&p, "https://my.url.com/test.git"));
+
+ cl_git_pass(git_fs_path_apply_relative(&p, "../another.git"));
+ cl_assert_equal_s("https://my.url.com/another.git", p.ptr);
+
+ cl_git_pass(git_fs_path_apply_relative(&p, "../full/path/url.patch"));
+ cl_assert_equal_s("https://my.url.com/full/path/url.patch", p.ptr);
+
+ cl_git_pass(git_fs_path_apply_relative(&p, ".."));
+ cl_assert_equal_s("https://my.url.com/full/path/", p.ptr);
+
+ cl_git_pass(git_fs_path_apply_relative(&p, "../../../"));
+ cl_assert_equal_s("https://", p.ptr);
+
+
+ cl_git_pass(git_str_sets(&p, "../../this/is/relative"));
+
+ cl_git_pass(git_fs_path_apply_relative(&p, "../../preserves/the/prefix"));
+ cl_assert_equal_s("../../this/preserves/the/prefix", p.ptr);
+
+ cl_git_pass(git_fs_path_apply_relative(&p, "../../../../that"));
+ cl_assert_equal_s("../../that", p.ptr);
+
+ cl_git_pass(git_fs_path_apply_relative(&p, "../there"));
+ cl_assert_equal_s("../../there", p.ptr);
+ git_str_dispose(&p);
+}
+
+static void assert_resolve_relative(
+ git_str *buf, const char *expected, const char *path)
+{
+ cl_git_pass(git_str_sets(buf, path));
+ cl_git_pass(git_fs_path_resolve_relative(buf, 0));
+ cl_assert_equal_s(expected, buf->ptr);
+}
+
+void test_path_core__15_resolve_relative(void)
+{
+ git_str buf = GIT_STR_INIT;
+
+ assert_resolve_relative(&buf, "", "");
+ assert_resolve_relative(&buf, "", ".");
+ assert_resolve_relative(&buf, "", "./");
+ assert_resolve_relative(&buf, "..", "..");
+ assert_resolve_relative(&buf, "../", "../");
+ assert_resolve_relative(&buf, "..", "./..");
+ assert_resolve_relative(&buf, "../", "./../");
+ assert_resolve_relative(&buf, "../", "../.");
+ assert_resolve_relative(&buf, "../", ".././");
+ assert_resolve_relative(&buf, "../..", "../..");
+ assert_resolve_relative(&buf, "../../", "../../");
+
+ assert_resolve_relative(&buf, "/", "/");
+ assert_resolve_relative(&buf, "/", "/.");
+
+ assert_resolve_relative(&buf, "", "a/..");
+ assert_resolve_relative(&buf, "", "a/../");
+ assert_resolve_relative(&buf, "", "a/../.");
+
+ assert_resolve_relative(&buf, "/a", "/a");
+ assert_resolve_relative(&buf, "/a/", "/a/.");
+ assert_resolve_relative(&buf, "/", "/a/../");
+ assert_resolve_relative(&buf, "/", "/a/../.");
+ assert_resolve_relative(&buf, "/", "/a/.././");
+
+ assert_resolve_relative(&buf, "a", "a");
+ assert_resolve_relative(&buf, "a/", "a/");
+ assert_resolve_relative(&buf, "a/", "a/.");
+ assert_resolve_relative(&buf, "a/", "a/./");
+
+ assert_resolve_relative(&buf, "a/b", "a//b");
+ assert_resolve_relative(&buf, "a/b/c", "a/b/c");
+ assert_resolve_relative(&buf, "b/c", "./b/c");
+ assert_resolve_relative(&buf, "a/c", "a/./c");
+ assert_resolve_relative(&buf, "a/b/", "a/b/.");
+
+ assert_resolve_relative(&buf, "/a/b/c", "///a/b/c");
+ assert_resolve_relative(&buf, "/", "////");
+ assert_resolve_relative(&buf, "/a", "///a");
+ assert_resolve_relative(&buf, "/", "///.");
+ assert_resolve_relative(&buf, "/", "///a/..");
+
+ assert_resolve_relative(&buf, "../../path", "../../test//../././path");
+ assert_resolve_relative(&buf, "../d", "a/b/../../../c/../d");
+
+ cl_git_pass(git_str_sets(&buf, "/.."));
+ cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
+
+ cl_git_pass(git_str_sets(&buf, "/./.."));
+ cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
+
+ cl_git_pass(git_str_sets(&buf, "/.//.."));
+ cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
+
+ cl_git_pass(git_str_sets(&buf, "/../."));
+ cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
+
+ cl_git_pass(git_str_sets(&buf, "/../.././../a"));
+ cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
+
+ cl_git_pass(git_str_sets(&buf, "////.."));
+ cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
+
+ /* things that start with Windows network paths */
+#ifdef GIT_WIN32
+ assert_resolve_relative(&buf, "//a/b/c", "//a/b/c");
+ assert_resolve_relative(&buf, "//a/", "//a/b/..");
+ assert_resolve_relative(&buf, "//a/b/c", "//a/Q/../b/x/y/../../c");
+
+ cl_git_pass(git_str_sets(&buf, "//a/b/../.."));
+ cl_git_fail(git_fs_path_resolve_relative(&buf, 0));
+#else
+ assert_resolve_relative(&buf, "/a/b/c", "//a/b/c");
+ assert_resolve_relative(&buf, "/a/", "//a/b/..");
+ assert_resolve_relative(&buf, "/a/b/c", "//a/Q/../b/x/y/../../c");
+ assert_resolve_relative(&buf, "/", "//a/b/../..");
+#endif
+
+ git_str_dispose(&buf);
+}
+
+#define assert_common_dirlen(i, p, q) \
+ cl_assert_equal_i((i), git_fs_path_common_dirlen((p), (q)));
+
+void test_path_core__16_resolve_relative(void)
+{
+ assert_common_dirlen(0, "", "");
+ assert_common_dirlen(0, "", "bar.txt");
+ assert_common_dirlen(0, "foo.txt", "bar.txt");
+ assert_common_dirlen(0, "foo.txt", "");
+ assert_common_dirlen(0, "foo/bar.txt", "bar/foo.txt");
+ assert_common_dirlen(0, "foo/bar.txt", "../foo.txt");
+
+ assert_common_dirlen(1, "/one.txt", "/two.txt");
+ assert_common_dirlen(4, "foo/one.txt", "foo/two.txt");
+ assert_common_dirlen(5, "/foo/one.txt", "/foo/two.txt");
+
+ assert_common_dirlen(6, "a/b/c/foo.txt", "a/b/c/d/e/bar.txt");
+ assert_common_dirlen(7, "/a/b/c/foo.txt", "/a/b/c/d/e/bar.txt");
+}
+
+static void fix_path(git_str *s)
+{
+#ifndef GIT_WIN32
+ GIT_UNUSED(s);
+#else
+ char* c;
+
+ for (c = s->ptr; *c; c++) {
+ if (*c == '/')
+ *c = '\\';
+ }
+#endif
+}
+
+void test_path_core__find_exe_in_path(void)
+{
+ char *orig_path;
+ git_str sandbox_path = GIT_STR_INIT;
+ git_str new_path = GIT_STR_INIT, full_path = GIT_STR_INIT,
+ dummy_path = GIT_STR_INIT;
+
+#ifdef GIT_WIN32
+ static const char *bogus_path_1 = "c:\\does\\not\\exist\\";
+ static const char *bogus_path_2 = "e:\\non\\existent";
+#else
+ static const char *bogus_path_1 = "/this/path/does/not/exist/";
+ static const char *bogus_path_2 = "/non/existent";
+#endif
+
+ orig_path = cl_getenv("PATH");
+
+ git_str_puts(&sandbox_path, clar_sandbox_path());
+ git_str_joinpath(&dummy_path, sandbox_path.ptr, "dummmmmmmy_libgit2_file");
+ cl_git_rewritefile(dummy_path.ptr, "this is a dummy file");
+
+ fix_path(&sandbox_path);
+ fix_path(&dummy_path);
+
+ cl_git_pass(git_str_printf(&new_path, "%s%c%s%c%s%c%s",
+ bogus_path_1, GIT_PATH_LIST_SEPARATOR,
+ orig_path, GIT_PATH_LIST_SEPARATOR,
+ sandbox_path.ptr, GIT_PATH_LIST_SEPARATOR,
+ bogus_path_2));
+
+ check_setenv("PATH", new_path.ptr);
+
+ cl_git_fail_with(GIT_ENOTFOUND, git_fs_path_find_executable(&full_path, "this_file_does_not_exist"));
+ cl_git_pass(git_fs_path_find_executable(&full_path, "dummmmmmmy_libgit2_file"));
+
+ cl_assert_equal_s(full_path.ptr, dummy_path.ptr);
+
+ git_str_dispose(&full_path);
+ git_str_dispose(&new_path);
+ git_str_dispose(&dummy_path);
+ git_str_dispose(&sandbox_path);
+ git__free(orig_path);
+}
+
+void test_path_core__validate_current_user_ownership(void)
+{
+ bool is_cur;
+
+ cl_must_pass(p_mkdir("testdir", 0777));
+ cl_git_pass(git_fs_path_owner_is_current_user(&is_cur, "testdir"));
+ cl_assert_equal_i(is_cur, 1);
+
+ cl_git_rewritefile("testfile", "This is a test file.");
+ cl_git_pass(git_fs_path_owner_is_current_user(&is_cur, "testfile"));
+ cl_assert_equal_i(is_cur, 1);
+
+#ifdef GIT_WIN32
+ cl_git_pass(git_fs_path_owner_is_current_user(&is_cur, "C:\\"));
+ cl_assert_equal_i(is_cur, 0);
+
+ cl_git_fail(git_fs_path_owner_is_current_user(&is_cur, "c:\\path\\does\\not\\exist"));
+#else
+ cl_git_pass(git_fs_path_owner_is_current_user(&is_cur, "/"));
+ cl_assert_equal_i(is_cur, (geteuid() == 0));
+
+ cl_git_fail(git_fs_path_owner_is_current_user(&is_cur, "/path/does/not/exist"));
+#endif
+}
+
+void test_path_core__dirlen(void)
+{
+ cl_assert_equal_sz(13, git_fs_path_dirlen("/foo/bar/asdf"));
+ cl_assert_equal_sz(13, git_fs_path_dirlen("/foo/bar/asdf/"));
+ cl_assert_equal_sz(13, git_fs_path_dirlen("/foo/bar/asdf//"));
+ cl_assert_equal_sz(3, git_fs_path_dirlen("foo////"));
+ cl_assert_equal_sz(3, git_fs_path_dirlen("foo"));
+ cl_assert_equal_sz(1, git_fs_path_dirlen("/"));
+ cl_assert_equal_sz(1, git_fs_path_dirlen("////"));
+ cl_assert_equal_sz(0, git_fs_path_dirlen(""));
+}
+
static void test_make_relative(
const char *expected_path,
const char *path,
@@ -341,3 +1119,29 @@ void test_path_core__join_unrooted_respects_funny_windows_roots(void)
test_join_unrooted("💩:/foo/bar/foobar", 13, "💩:/foo/bar/foobar", "💩:/foo/bar");
test_join_unrooted("💩:/foo/bar/foobar", 9, "💩:/foo/bar/foobar", "💩:/foo/");
}
+
+void test_path_core__is_root(void)
+{
+ cl_assert_equal_b(true, git_fs_path_is_root("/"));
+ cl_assert_equal_b(false, git_fs_path_is_root("//"));
+ cl_assert_equal_b(false, git_fs_path_is_root("foo/"));
+ cl_assert_equal_b(false, git_fs_path_is_root("/foo/"));
+ cl_assert_equal_b(false, git_fs_path_is_root("/foo"));
+ cl_assert_equal_b(false, git_fs_path_is_root("\\"));
+
+#ifdef GIT_WIN32
+ cl_assert_equal_b(true, git_fs_path_is_root("A:\\"));
+ cl_assert_equal_b(false, git_fs_path_is_root("B:\\foo"));
+ cl_assert_equal_b(false, git_fs_path_is_root("B:\\foo\\"));
+ cl_assert_equal_b(true, git_fs_path_is_root("C:\\"));
+ cl_assert_equal_b(true, git_fs_path_is_root("c:\\"));
+ cl_assert_equal_b(true, git_fs_path_is_root("z:\\"));
+ cl_assert_equal_b(false, git_fs_path_is_root("z:\\\\"));
+ cl_assert_equal_b(false, git_fs_path_is_root("\\\\localhost"));
+ cl_assert_equal_b(false, git_fs_path_is_root("\\\\localhost\\"));
+ cl_assert_equal_b(false, git_fs_path_is_root("\\\\localhost\\c$\\"));
+ cl_assert_equal_b(false, git_fs_path_is_root("\\\\localhost\\c$\\Foo"));
+ cl_assert_equal_b(false, git_fs_path_is_root("\\\\localhost\\c$\\Foo\\"));
+ cl_assert_equal_b(false, git_fs_path_is_root("\\\\Volume\\12345\\Foo\\Bar.txt"));
+#endif
+}
diff --git a/tests/util/path/win32.c b/tests/util/path/win32.c
index 1aaf686..6f90b44 100644
--- a/tests/util/path/win32.c
+++ b/tests/util/path/win32.c
@@ -278,5 +278,38 @@ void test_path_win32__8dot3_name(void)
cl_must_pass(p_mkdir(".bar", 0777));
cl_assert_equal_s("BAR~2", (shortname = git_win32_path_8dot3_name(".bar")));
git__free(shortname);
+
+ p_rmdir(".foo");
+ p_rmdir(".bar");
+ p_unlink("bar~1");
+#endif
+}
+
+void test_path_win32__realpath(void)
+{
+#ifdef GIT_WIN32
+ git_str expected = GIT_STR_INIT;
+ char result[GIT_PATH_MAX];
+
+ /* Ensure relative paths become absolute */
+ cl_must_pass(git_str_joinpath(&expected, clar_sandbox_path(), "abcdef"));
+ cl_must_pass(p_mkdir("abcdef", 0777));
+ cl_assert(p_realpath("./abcdef", result) != NULL);
+ cl_assert_equal_s(expected.ptr, result);
+
+ /* Ensure case is canonicalized */
+ git_str_clear(&expected);
+ cl_must_pass(git_str_joinpath(&expected, clar_sandbox_path(), "FOO"));
+ cl_must_pass(p_mkdir("FOO", 0777));
+ cl_assert(p_realpath("foo", result) != NULL);
+ cl_assert_equal_s(expected.ptr, result);
+
+ cl_assert(p_realpath("nonexistent", result) == NULL);
+ cl_assert_equal_i(ENOENT, errno);
+
+ git_str_dispose(&expected);
+
+ p_rmdir("abcdef");
+ p_rmdir("FOO");
#endif
}
diff --git a/tests/util/process/env.c b/tests/util/process/env.c
new file mode 100644
index 0000000..bb7dbcd
--- /dev/null
+++ b/tests/util/process/env.c
@@ -0,0 +1,111 @@
+#include "clar_libgit2.h"
+#include "process.h"
+#include "vector.h"
+
+static git_str env_cmd = GIT_STR_INIT;
+static git_str accumulator = GIT_STR_INIT;
+static git_vector env_result = GIT_VECTOR_INIT;
+
+void test_process_env__initialize(void)
+{
+#ifdef GIT_WIN32
+ git_str_printf(&env_cmd, "%s/env.cmd", cl_fixture("process"));
+#else
+ git_str_puts(&env_cmd, "/usr/bin/env");
+#endif
+
+ cl_git_pass(git_vector_init(&env_result, 32, git__strcmp_cb));
+}
+
+void test_process_env__cleanup(void)
+{
+ git_vector_free(&env_result);
+ git_str_dispose(&accumulator);
+ git_str_dispose(&env_cmd);
+}
+
+static void run_env(const char **env_array, size_t env_len, bool exclude_env)
+{
+ const char *args_array[] = { env_cmd.ptr };
+
+ git_process *process;
+ git_process_options opts = GIT_PROCESS_OPTIONS_INIT;
+ git_process_result result = GIT_PROCESS_RESULT_INIT;
+
+ char buf[1024], *tok;
+ ssize_t ret;
+
+ opts.capture_out = 1;
+ opts.exclude_env = exclude_env;
+
+ cl_git_pass(git_process_new(&process, args_array, ARRAY_SIZE(args_array), env_array, env_len, &opts));
+ cl_git_pass(git_process_start(process));
+
+ while ((ret = git_process_read(process, buf, 1024)) > 0)
+ cl_git_pass(git_str_put(&accumulator, buf, (size_t)ret));
+
+ cl_assert_equal_i(0, ret);
+
+ cl_git_pass(git_process_wait(&result, process));
+
+ cl_assert_equal_i(GIT_PROCESS_STATUS_NORMAL, result.status);
+ cl_assert_equal_i(0, result.exitcode);
+ cl_assert_equal_i(0, result.signal);
+
+ for (tok = strtok(accumulator.ptr, "\n"); tok; tok = strtok(NULL, "\n")) {
+#ifdef GIT_WIN32
+ if (strlen(tok) && tok[strlen(tok) - 1] == '\r')
+ tok[strlen(tok) - 1] = '\0';
+#endif
+
+ cl_git_pass(git_vector_insert(&env_result, tok));
+ }
+
+ git_process_close(process);
+ git_process_free(process);
+}
+
+void test_process_env__can_add_env(void)
+{
+ const char *env_array[] = { "TEST_NEW_ENV=added", "TEST_OTHER_ENV=also_added" };
+ run_env(env_array, 2, false);
+
+ cl_git_pass(git_vector_search(NULL, &env_result, "TEST_NEW_ENV=added"));
+ cl_git_pass(git_vector_search(NULL, &env_result, "TEST_OTHER_ENV=also_added"));
+}
+
+void test_process_env__can_propagate_env(void)
+{
+ cl_setenv("TEST_NEW_ENV", "propagated");
+ run_env(NULL, 0, false);
+
+ cl_git_pass(git_vector_search(NULL, &env_result, "TEST_NEW_ENV=propagated"));
+}
+
+void test_process_env__can_remove_env(void)
+{
+ const char *env_array[] = { "TEST_NEW_ENV=" };
+ char *str;
+ size_t i;
+
+ cl_setenv("TEST_NEW_ENV", "propagated");
+ run_env(env_array, 1, false);
+
+ git_vector_foreach(&env_result, i, str)
+ cl_assert(git__prefixcmp(str, "TEST_NEW_ENV=") != 0);
+}
+
+void test_process_env__can_clear_env(void)
+{
+ const char *env_array[] = { "TEST_NEW_ENV=added", "TEST_OTHER_ENV=also_added" };
+
+ cl_setenv("SOME_EXISTING_ENV", "propagated");
+ run_env(env_array, 2, true);
+
+ /*
+ * We can't simply test that the environment is precisely what we
+ * provided. Some systems (eg win32) will add environment variables
+ * to all processes.
+ */
+ cl_assert_equal_i(GIT_ENOTFOUND, git_vector_search(NULL, &env_result, "SOME_EXISTING_ENV=propagated"));
+}
diff --git a/tests/util/process/start.c b/tests/util/process/start.c
new file mode 100644
index 0000000..19ae5e3
--- /dev/null
+++ b/tests/util/process/start.c
@@ -0,0 +1,247 @@
+#include "clar_libgit2.h"
+#include "process.h"
+#include "vector.h"
+
+#ifndef GIT_WIN32
+# include <signal.h>
+#endif
+
+#ifndef SIGTERM
+# define SIGTERM 42
+#endif
+
+#ifndef SIGPIPE
+# define SIGPIPE 42
+#endif
+
+static git_str helloworld_cmd = GIT_STR_INIT;
+static git_str cat_cmd = GIT_STR_INIT;
+static git_str pwd_cmd = GIT_STR_INIT;
+
+void test_process_start__initialize(void)
+{
+#ifdef GIT_WIN32
+ git_str_printf(&helloworld_cmd, "%s/helloworld.bat", cl_fixture("process"));
+ git_str_printf(&cat_cmd, "%s/cat.bat", cl_fixture("process"));
+ git_str_printf(&pwd_cmd, "%s/pwd.bat", cl_fixture("process"));
+#else
+ git_str_printf(&helloworld_cmd, "%s/helloworld.sh", cl_fixture("process"));
+#endif
+}
+
+void test_process_start__cleanup(void)
+{
+ git_str_dispose(&pwd_cmd);
+ git_str_dispose(&cat_cmd);
+ git_str_dispose(&helloworld_cmd);
+}
+
+void test_process_start__returncode(void)
+{
+#if defined(GIT_WIN32)
+ const char *args_array[] = { "C:\\Windows\\System32\\cmd.exe", "/c", "exit", "1" };
+#elif defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__) || \
+ defined(__MidnightBSD__) || defined(__DragonFly__)
+ const char *args_array[] = { "/usr/bin/false" };
+#else
+ const char *args_array[] = { "/bin/false" };
+#endif
+
+ git_process *process;
+ git_process_options opts = GIT_PROCESS_OPTIONS_INIT;
+ git_process_result result = GIT_PROCESS_RESULT_INIT;
+
+ cl_git_pass(git_process_new(&process, args_array, ARRAY_SIZE(args_array), NULL, 0, &opts));
+ cl_git_pass(git_process_start(process));
+ cl_git_pass(git_process_wait(&result, process));
+
+ cl_assert_equal_i(GIT_PROCESS_STATUS_NORMAL, result.status);
+ cl_assert_equal_i(1, result.exitcode);
+ cl_assert_equal_i(0, result.signal);
+
+ git_process_free(process);
+}
+
+void test_process_start__not_found(void)
+{
+#ifdef GIT_WIN32
+ const char *args_array[] = { "C:\\a\\b\\z\\y\\not_found" };
+#else
+ const char *args_array[] = { "/a/b/z/y/not_found" };
+#endif
+
+ git_process *process;
+ git_process_options opts = GIT_PROCESS_OPTIONS_INIT;
+
+ cl_git_pass(git_process_new(&process, args_array, ARRAY_SIZE(args_array), NULL, 0, &opts));
+ cl_git_fail(git_process_start(process));
+ git_process_free(process);
+}
+
+static void write_all(git_process *process, char *buf)
+{
+ size_t buf_len = strlen(buf);
+ ssize_t ret;
+
+ while (buf_len) {
+ ret = git_process_write(process, buf, buf_len);
+ cl_git_pass(ret < 0 ? (int)ret : 0);
+
+ buf += ret;
+ buf_len -= ret;
+ }
+}
+
+static void read_all(git_str *out, git_process *process)
+{
+ char buf[32];
+ size_t buf_len = 32;
+ ssize_t ret;
+
+ while ((ret = git_process_read(process, buf, buf_len)) > 0)
+ cl_git_pass(git_str_put(out, buf, ret));
+
+ cl_git_pass(ret < 0 ? (int)ret : 0);
+}
+
+void test_process_start__redirect_stdio(void)
+{
+#ifdef GIT_WIN32
+ const char *args_array[] = { "C:\\Windows\\System32\\cmd.exe", "/c", cat_cmd.ptr };
+#else
+ const char *args_array[] = { "/bin/cat" };
+#endif
+
+ git_process *process;
+ git_process_options opts = GIT_PROCESS_OPTIONS_INIT;
+ git_process_result result = GIT_PROCESS_RESULT_INIT;
+ git_str buf = GIT_STR_INIT;
+
+ opts.capture_in = 1;
+ opts.capture_out = 1;
+
+ cl_git_pass(git_process_new(&process, args_array, ARRAY_SIZE(args_array), NULL, 0, &opts));
+ cl_git_pass(git_process_start(process));
+
+ write_all(process, "Hello, world.\r\nHello!\r\n");
+ cl_git_pass(git_process_close_in(process));
+
+ read_all(&buf, process);
+ cl_assert_equal_s("Hello, world.\r\nHello!\r\n", buf.ptr);
+
+ cl_git_pass(git_process_wait(&result, process));
+
+ cl_assert_equal_i(GIT_PROCESS_STATUS_NORMAL, result.status);
+ cl_assert_equal_i(0, result.exitcode);
+ cl_assert_equal_i(0, result.signal);
+
+ git_str_dispose(&buf);
+ git_process_free(process);
+}
+
+/*
+void test_process_start__catch_sigterm(void)
+{
+ const char *args_array[] = { "/bin/cat" };
+
+ git_process *process;
+ git_process_options opts = GIT_PROCESS_OPTIONS_INIT;
+ git_process_result result = GIT_PROCESS_RESULT_INIT;
+ p_pid_t pid;
+
+ opts.capture_out = 1;
+
+ cl_git_pass(git_process_new(&process, args_array, ARRAY_SIZE(args_array), NULL, 0, &opts));
+ cl_git_pass(git_process_start(process));
+ cl_git_pass(git_process_id(&pid, process));
+
+ cl_must_pass(kill(pid, SIGTERM));
+
+ cl_git_pass(git_process_wait(&result, process));
+
+ cl_assert_equal_i(GIT_PROCESS_STATUS_ERROR, result.status);
+ cl_assert_equal_i(0, result.exitcode);
+ cl_assert_equal_i(SIGTERM, result.signal);
+
+ git_process_free(process);
+}
+
+void test_process_start__catch_sigpipe(void)
+{
+ const char *args_array[] = { helloworld_cmd.ptr };
+
+ git_process *process;
+ git_process_options opts = GIT_PROCESS_OPTIONS_INIT;
+ git_process_result result = GIT_PROCESS_RESULT_INIT;
+
+ opts.capture_out = 1;
+
+ cl_git_pass(git_process_new(&process, args_array, ARRAY_SIZE(args_array), NULL, 0, &opts));
+ cl_git_pass(git_process_start(process));
+ cl_git_pass(git_process_close(process));
+ cl_git_pass(git_process_wait(&result, process));
+
+ cl_assert_equal_i(GIT_PROCESS_STATUS_ERROR, result.status);
+ cl_assert_equal_i(0, result.exitcode);
+ cl_assert_equal_i(SIGPIPE, result.signal);
+
+ git_process_free(process);
+}
+*/
+
+void test_process_start__can_chdir(void)
+{
+#ifdef GIT_WIN32
+ const char *args_array[] = { "C:\\Windows\\System32\\cmd.exe", "/c", pwd_cmd.ptr };
+ char *startwd = "C:\\";
+#else
+ const char *args_array[] = { "/bin/pwd" };
+ char *startwd = "/";
+#endif
+
+ git_process *process;
+ git_process_options opts = GIT_PROCESS_OPTIONS_INIT;
+ git_process_result result = GIT_PROCESS_RESULT_INIT;
+ git_str buf = GIT_STR_INIT;
+
+ opts.cwd = startwd;
+ opts.capture_out = 1;
+
+ cl_git_pass(git_process_new(&process, args_array, ARRAY_SIZE(args_array), NULL, 0, &opts));
+ cl_git_pass(git_process_start(process));
+
+ read_all(&buf, process);
+ git_str_rtrim(&buf);
+
+ cl_assert_equal_s(startwd, buf.ptr);
+
+ cl_git_pass(git_process_wait(&result, process));
+
+ cl_assert_equal_i(GIT_PROCESS_STATUS_NORMAL, result.status);
+ cl_assert_equal_i(0, result.exitcode);
+ cl_assert_equal_i(0, result.signal);
+
+ git_str_dispose(&buf);
+ git_process_free(process);
+}
+
+void test_process_start__cannot_chdir_to_nonexistent_dir(void)
+{
+#ifdef GIT_WIN32
+ const char *args_array[] = { "C:\\Windows\\System32\\cmd.exe", "/c", pwd_cmd.ptr };
+ char *startwd = "C:\\a\\b\\z\\y\\not_found";
+#else
+ const char *args_array[] = { "/bin/pwd" };
+ char *startwd = "/a/b/z/y/not_found";
+#endif
+
+ git_process *process;
+ git_process_options opts = GIT_PROCESS_OPTIONS_INIT;
+
+ opts.cwd = startwd;
+ opts.capture_out = 1;
+
+ cl_git_pass(git_process_new(&process, args_array, ARRAY_SIZE(args_array), NULL, 0, &opts));
+ cl_git_fail(git_process_start(process));
+ git_process_free(process);
+}
diff --git a/tests/util/process/win32.c b/tests/util/process/win32.c
new file mode 100644
index 0000000..c04a56e
--- /dev/null
+++ b/tests/util/process/win32.c
@@ -0,0 +1,63 @@
+#include "clar_libgit2.h"
+#include "process.h"
+#include "vector.h"
+
+#ifdef GIT_WIN32
+static git_str result;
+
+# define assert_cmdline(expected, given) do { \
+ cl_git_pass(git_process__cmdline(&result, given, ARRAY_SIZE(given))); \
+ cl_assert_equal_s(expected, result.ptr); \
+ git_str_dispose(&result); \
+ } while(0)
+
+#endif
+
+
+void test_process_win32__cmdline_is_whitespace_delimited(void)
+{
+#ifdef GIT_WIN32
+ const char *one[] = { "one" };
+ const char *two[] = { "one", "two" };
+ const char *three[] = { "one", "two", "three" };
+ const char *four[] = { "one", "two", "three", "four" };
+
+ assert_cmdline("one", one);
+ assert_cmdline("one two", two);
+ assert_cmdline("one two three", three);
+ assert_cmdline("one two three four", four);
+#endif
+}
+
+void test_process_win32__cmdline_escapes_whitespace(void)
+{
+#ifdef GIT_WIN32
+ const char *spaces[] = { "one with spaces" };
+ const char *tabs[] = { "one\twith\ttabs" };
+ const char *multiple[] = { "one with many spaces" };
+
+ assert_cmdline("one\" \"with\" \"spaces", spaces);
+ assert_cmdline("one\"\t\"with\"\t\"tabs", tabs);
+ assert_cmdline("one\" \"with\" \"many\" \"spaces", multiple);
+#endif
+}
+
+void test_process_win32__cmdline_escapes_quotes(void)
+{
+#ifdef GIT_WIN32
+ const char *one[] = { "echo", "\"hello world\"" };
+
+ assert_cmdline("echo \\\"hello\" \"world\\\"", one);
+#endif
+}
+
+void test_process_win32__cmdline_escapes_backslash(void)
+{
+#ifdef GIT_WIN32
+ const char *one[] = { "foo\\bar", "foo\\baz" };
+ const char *two[] = { "c:\\program files\\foo bar\\foo bar.exe", "c:\\path\\to\\other\\", "/a", "/b" };
+
+ assert_cmdline("foo\\\\bar foo\\\\baz", one);
+ assert_cmdline("c:\\\\program\" \"files\\\\foo\" \"bar\\\\foo\" \"bar.exe c:\\\\path\\\\to\\\\other\\\\ /a /b", two);
+#endif
+}
diff --git a/tests/util/string.c b/tests/util/string.c
index de04dea..051f8c3 100644
--- a/tests/util/string.c
+++ b/tests/util/string.c
@@ -111,12 +111,6 @@ void test_string__strcasecmp(void)
cl_assert(git__strcasecmp("foo", "FOO") == 0);
cl_assert(git__strcasecmp("foo", "fOO") == 0);
- cl_assert(strcasecmp("rt\303\202of", "rt dev\302\266h") > 0);
- cl_assert(strcasecmp("e\342\202\254ghi=", "et") > 0);
- cl_assert(strcasecmp("rt dev\302\266h", "rt\303\202of") < 0);
- cl_assert(strcasecmp("et", "e\342\202\254ghi=") < 0);
- cl_assert(strcasecmp("\303\215", "\303\255") < 0);
-
cl_assert(git__strcasecmp("rt\303\202of", "rt dev\302\266h") > 0);
cl_assert(git__strcasecmp("e\342\202\254ghi=", "et") > 0);
cl_assert(git__strcasecmp("rt dev\302\266h", "rt\303\202of") < 0);