diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/clar_libgit2.c | 53 | ||||
-rw-r--r-- | tests/clar_libgit2.h | 11 | ||||
-rw-r--r-- | tests/core/buffer.c | 20 | ||||
-rw-r--r-- | tests/core/env.c | 2 | ||||
-rw-r--r-- | tests/core/link.c | 602 | ||||
-rw-r--r-- | tests/diff/binary.c | 263 | ||||
-rw-r--r-- | tests/diff/format_email.c | 193 | ||||
-rw-r--r-- | tests/diff/patch.c | 1 | ||||
-rw-r--r-- | tests/diff/stats.c | 357 | ||||
-rw-r--r-- | tests/fetchhead/fetchhead_data.h | 3 | ||||
-rw-r--r-- | tests/fetchhead/nonetwork.c | 9 | ||||
-rw-r--r-- | tests/merge/workdir/dirty.c | 30 | ||||
-rw-r--r-- | tests/merge/workdir/simple.c | 6 | ||||
-rw-r--r-- | tests/reset/default.c | 39 | ||||
-rw-r--r-- | tests/stash/save.c | 36 | ||||
-rw-r--r-- | tests/stash/stash_helpers.c | 14 | ||||
-rw-r--r-- | tests/status/renames.c | 201 |
17 files changed, 1360 insertions, 480 deletions
diff --git a/tests/clar_libgit2.c b/tests/clar_libgit2.c index 90e53c5e6..6f6143dad 100644 --- a/tests/clar_libgit2.c +++ b/tests/clar_libgit2.c @@ -59,47 +59,40 @@ void cl_git_rewritefile(const char *path, const char *content) char *cl_getenv(const char *name) { - git_win32_path name_utf16; - DWORD alloc_len; - wchar_t *value_utf16; - char *value_utf8; + wchar_t *wide_name, *wide_value; + char *utf8_value = NULL; + DWORD value_len; - git_win32_path_from_c(name_utf16, name); - alloc_len = GetEnvironmentVariableW(name_utf16, NULL, 0); - if (alloc_len <= 0) - return NULL; + cl_assert(git__utf8_to_16_alloc(&wide_name, name) >= 0); - cl_assert(value_utf16 = git__calloc(alloc_len, sizeof(wchar_t))); + value_len = GetEnvironmentVariableW(wide_name, NULL, 0); - GetEnvironmentVariableW(name_utf16, value_utf16, alloc_len); - - alloc_len = alloc_len * 4 + 1; /* worst case UTF16->UTF8 growth */ - cl_assert(value_utf8 = git__calloc(alloc_len, 1)); - - git__utf16_to_8(value_utf8, alloc_len, value_utf16); - - git__free(value_utf16); + if (value_len) { + cl_assert(wide_value = git__malloc(value_len * sizeof(wchar_t))); + cl_assert(GetEnvironmentVariableW(wide_name, wide_value, value_len)); + cl_assert(git__utf16_to_8_alloc(&utf8_value, wide_value) >= 0); + git__free(wide_value); + } - return value_utf8; + git__free(wide_name); + return utf8_value; } int cl_setenv(const char *name, const char *value) { - git_win32_path name_utf16; - git_win32_path value_utf16; + wchar_t *wide_name, *wide_value; - git_win32_path_from_c(name_utf16, name); + cl_assert(git__utf8_to_16_alloc(&wide_name, name) >= 0); if (value) { - git_win32_path_from_c(value_utf16, value); - cl_assert(SetEnvironmentVariableW(name_utf16, value_utf16)); + cl_assert(git__utf8_to_16_alloc(&wide_value, value) >= 0); + cl_assert(SetEnvironmentVariableW(wide_name, wide_value)); } else { /* Windows XP returns 0 (failed) when passing NULL for lpValue when - * lpName does not exist in the environment block. This behavior - * seems to have changed in later versions. Don't check return value - * of SetEnvironmentVariable when passing NULL for lpValue. - */ - SetEnvironmentVariableW(name_utf16, NULL); + * lpName does not exist in the environment block. This behavior + * seems to have changed in later versions. Don't check the return value + * of SetEnvironmentVariable when passing NULL for lpValue. */ + SetEnvironmentVariableW(wide_name, NULL); } return 0; @@ -115,8 +108,8 @@ int cl_rename(const char *source, const char *dest) git_win32_path dest_utf16; unsigned retries = 1; - git_win32_path_from_c(source_utf16, source); - git_win32_path_from_c(dest_utf16, dest); + cl_assert(git_win32_path_from_utf8(source_utf16, source) >= 0); + cl_assert(git_win32_path_from_utf8(dest_utf16, dest) >= 0); while (!MoveFileW(source_utf16, dest_utf16)) { /* Only retry if the error is ERROR_ACCESS_DENIED; diff --git a/tests/clar_libgit2.h b/tests/clar_libgit2.h index d395bd66f..082fa9f4a 100644 --- a/tests/clar_libgit2.h +++ b/tests/clar_libgit2.h @@ -29,6 +29,17 @@ #define cl_git_fail_with(expr, error) cl_assert_equal_i(error,expr) +/** + * Like cl_git_pass, only for Win32 error code conventions + */ +#define cl_win32_pass(expr) do { \ + int _win32_res; \ + if ((_win32_res = (expr)) == 0) { \ + giterr_set(GITERR_OS, "Returned: %d, system error code: %d", _win32_res, GetLastError()); \ + cl_git_report_failure(_win32_res, __FILE__, __LINE__, "System call failed: " #expr); \ + } \ + } while(0) + void cl_git_report_failure(int, const char *, int, const char *); #define cl_assert_at_line(expr,file,line) \ diff --git a/tests/core/buffer.c b/tests/core/buffer.c index eb1d95a95..da5ec605c 100644 --- a/tests/core/buffer.c +++ b/tests/core/buffer.c @@ -773,6 +773,26 @@ void test_core_buffer__base64(void) git_buf_free(&buf); } +void test_core_buffer__base85(void) +{ + git_buf buf = GIT_BUF_INIT; + + cl_git_pass(git_buf_put_base85(&buf, "this", 4)); + cl_assert_equal_s("bZBXF", buf.ptr); + git_buf_clear(&buf); + + cl_git_pass(git_buf_put_base85(&buf, "two rnds", 8)); + cl_assert_equal_s("ba!tca&BaE", buf.ptr); + git_buf_clear(&buf); + + cl_git_pass(git_buf_put_base85(&buf, "this is base 85 encoded", + strlen("this is base 85 encoded"))); + cl_assert_equal_s("bZBXFAZc?TVqtS-AUHK3Wo~0{WMyOk", buf.ptr); + git_buf_clear(&buf); + + git_buf_free(&buf); +} + void test_core_buffer__classify_with_utf8(void) { char *data0 = "Simple text\n"; diff --git a/tests/core/env.c b/tests/core/env.c index b01ad1c24..df1d92a02 100644 --- a/tests/core/env.c +++ b/tests/core/env.c @@ -21,7 +21,7 @@ static char *home_values[] = { "f\xc4\x80ke_\xc4\xa4ome", /* latin extended */ "f\xce\xb1\xce\xba\xce\xb5_h\xce\xbfm\xce\xad", /* having fun with greek */ "fa\xe0" "\xb8" "\x87" "e_\xe0" "\xb8" "\x99" "ome", /* thai characters */ - "f\xe1\x9cx80ke_\xe1\x9c\x91ome", /* tagalog characters */ + "f\xe1\x9c\x80ke_\xe1\x9c\x91ome", /* tagalog characters */ "\xe1\xb8\x9f\xe1\xba\xa2" "ke_ho" "\xe1" "\xb9" "\x81" "e", /* latin extended additional */ "\xf0\x9f\x98\x98\xf0\x9f\x98\x82", /* emoticons */ NULL diff --git a/tests/core/link.c b/tests/core/link.c new file mode 100644 index 000000000..1794a3893 --- /dev/null +++ b/tests/core/link.c @@ -0,0 +1,602 @@ +#include "clar_libgit2.h" +#include "posix.h" +#include "buffer.h" +#include "path.h" + +#ifdef GIT_WIN32 +# include "win32/reparse.h" +#endif + +void test_core_link__cleanup(void) +{ +#ifdef GIT_WIN32 + RemoveDirectory("lstat_junction"); + RemoveDirectory("lstat_dangling"); + RemoveDirectory("lstat_dangling_dir"); + RemoveDirectory("lstat_dangling_junction"); + + RemoveDirectory("stat_junction"); + RemoveDirectory("stat_dangling"); + RemoveDirectory("stat_dangling_dir"); + RemoveDirectory("stat_dangling_junction"); +#endif +} + +#ifdef GIT_WIN32 +static bool is_administrator(void) +{ + static SID_IDENTIFIER_AUTHORITY authority = { SECURITY_NT_AUTHORITY }; + PSID admin_sid; + BOOL is_admin; + + cl_win32_pass(AllocateAndInitializeSid(&authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &admin_sid)); + cl_win32_pass(CheckTokenMembership(NULL, admin_sid, &is_admin)); + FreeSid(admin_sid); + + return is_admin ? true : false; +} +#endif + +static void do_symlink(const char *old, const char *new, int is_dir) +{ +#ifndef GIT_WIN32 + GIT_UNUSED(is_dir); + + cl_must_pass(symlink(old, new)); +#else + typedef DWORD (WINAPI *create_symlink_func)(LPCTSTR, LPCTSTR, DWORD); + HMODULE module; + create_symlink_func pCreateSymbolicLink; + + if (!is_administrator()) + clar__skip(); + + cl_assert(module = GetModuleHandle("kernel32")); + cl_assert(pCreateSymbolicLink = (create_symlink_func)GetProcAddress(module, "CreateSymbolicLinkA")); + + cl_win32_pass(pCreateSymbolicLink(new, old, is_dir)); +#endif +} + +static void do_hardlink(const char *old, const char *new) +{ +#ifndef GIT_WIN32 + cl_must_pass(link(old, new)); +#else + typedef DWORD (WINAPI *create_hardlink_func)(LPCTSTR, LPCTSTR, LPSECURITY_ATTRIBUTES); + HMODULE module; + create_hardlink_func pCreateHardLink; + + if (!is_administrator()) + clar__skip(); + + cl_assert(module = GetModuleHandle("kernel32")); + cl_assert(pCreateHardLink = (create_hardlink_func)GetProcAddress(module, "CreateHardLinkA")); + + cl_win32_pass(pCreateHardLink(new, old, 0)); +#endif +} + +#ifdef GIT_WIN32 + +static void do_junction(const char *old, const char *new) +{ + GIT_REPARSE_DATA_BUFFER *reparse_buf; + HANDLE handle; + git_buf unparsed_buf = GIT_BUF_INIT; + wchar_t *subst_utf16, *print_utf16; + DWORD ioctl_ret; + int subst_utf16_len, subst_byte_len, print_utf16_len, print_byte_len, ret; + USHORT reparse_buflen; + size_t i; + + /* Junction targets must be the unparsed name, starting with \??\, using + * backslashes instead of forward, and end in a trailing backslash. + * eg: \??\C:\Foo\ + */ + git_buf_puts(&unparsed_buf, "\\??\\"); + + for (i = 0; i < strlen(old); i++) + git_buf_putc(&unparsed_buf, old[i] == '/' ? '\\' : old[i]); + + git_buf_putc(&unparsed_buf, '\\'); + + subst_utf16_len = git__utf8_to_16(NULL, 0, git_buf_cstr(&unparsed_buf)); + subst_byte_len = subst_utf16_len * sizeof(WCHAR); + + print_utf16_len = subst_utf16_len - 4; + print_byte_len = subst_byte_len - (4 * sizeof(WCHAR)); + + /* The junction must be an empty directory before the junction attribute + * can be added. + */ + cl_win32_pass(CreateDirectoryA(new, NULL)); + + handle = CreateFileA(new, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); + cl_win32_pass(handle != INVALID_HANDLE_VALUE); + + reparse_buflen = (USHORT)(REPARSE_DATA_HEADER_SIZE + + REPARSE_DATA_MOUNTPOINT_HEADER_SIZE + + subst_byte_len + sizeof(WCHAR) + + print_byte_len + sizeof(WCHAR)); + + reparse_buf = LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, reparse_buflen); + cl_assert(reparse_buf); + + subst_utf16 = reparse_buf->MountPointReparseBuffer.PathBuffer; + print_utf16 = subst_utf16 + subst_utf16_len + 1; + + ret = git__utf8_to_16(subst_utf16, subst_utf16_len + 1, + git_buf_cstr(&unparsed_buf)); + cl_assert_equal_i(subst_utf16_len, ret); + + ret = git__utf8_to_16(print_utf16, + print_utf16_len + 1, git_buf_cstr(&unparsed_buf) + 4); + cl_assert_equal_i(print_utf16_len, ret); + + reparse_buf->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; + reparse_buf->MountPointReparseBuffer.SubstituteNameOffset = 0; + reparse_buf->MountPointReparseBuffer.SubstituteNameLength = subst_byte_len; + reparse_buf->MountPointReparseBuffer.PrintNameOffset = (USHORT)(subst_byte_len + sizeof(WCHAR)); + reparse_buf->MountPointReparseBuffer.PrintNameLength = print_byte_len; + reparse_buf->ReparseDataLength = reparse_buflen - REPARSE_DATA_HEADER_SIZE; + + cl_win32_pass(DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, + reparse_buf, reparse_buflen, NULL, 0, &ioctl_ret, NULL)); + + CloseHandle(handle); + LocalFree(reparse_buf); +} + +static void do_custom_reparse(const char *path) +{ + REPARSE_GUID_DATA_BUFFER *reparse_buf; + HANDLE handle; + DWORD ioctl_ret; + + const char *reparse_data = "Reparse points are silly."; + size_t reparse_buflen = REPARSE_GUID_DATA_BUFFER_HEADER_SIZE + + strlen(reparse_data) + 1; + + reparse_buf = LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, reparse_buflen); + cl_assert(reparse_buf); + + reparse_buf->ReparseTag = 42; + reparse_buf->ReparseDataLength = (WORD)(strlen(reparse_data) + 1); + + reparse_buf->ReparseGuid.Data1 = 0xdeadbeef; + reparse_buf->ReparseGuid.Data2 = 0xdead; + reparse_buf->ReparseGuid.Data3 = 0xbeef; + reparse_buf->ReparseGuid.Data4[0] = 42; + reparse_buf->ReparseGuid.Data4[1] = 42; + reparse_buf->ReparseGuid.Data4[2] = 42; + reparse_buf->ReparseGuid.Data4[3] = 42; + reparse_buf->ReparseGuid.Data4[4] = 42; + reparse_buf->ReparseGuid.Data4[5] = 42; + reparse_buf->ReparseGuid.Data4[6] = 42; + reparse_buf->ReparseGuid.Data4[7] = 42; + reparse_buf->ReparseGuid.Data4[8] = 42; + + memcpy(reparse_buf->GenericReparseBuffer.DataBuffer, + reparse_data, strlen(reparse_data) + 1); + + handle = CreateFileA(path, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); + cl_win32_pass(handle != INVALID_HANDLE_VALUE); + + cl_win32_pass(DeviceIoControl(handle, FSCTL_SET_REPARSE_POINT, + reparse_buf, + reparse_buf->ReparseDataLength + REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, + NULL, 0, &ioctl_ret, NULL)); + + CloseHandle(handle); + LocalFree(reparse_buf); +} + +#endif + +git_buf *unslashify(git_buf *buf) +{ +#ifdef GIT_WIN32 + size_t i; + + for (i = 0; i < buf->size; i++) + if (buf->ptr[i] == '/') + buf->ptr[i] = '\\'; +#endif + + return buf; +} + +void test_core_link__stat_regular_file(void) +{ + struct stat st; + + cl_git_rewritefile("stat_regfile", "This is a regular file!\n"); + + cl_must_pass(p_stat("stat_regfile", &st)); + cl_assert(S_ISREG(st.st_mode)); + cl_assert_equal_i(24, st.st_size); +} + +void test_core_link__lstat_regular_file(void) +{ + struct stat st; + + cl_git_rewritefile("lstat_regfile", "This is a regular file!\n"); + + cl_must_pass(p_stat("lstat_regfile", &st)); + cl_assert(S_ISREG(st.st_mode)); + cl_assert_equal_i(24, st.st_size); +} + +void test_core_link__stat_symlink(void) +{ + struct stat st; + + cl_git_rewritefile("stat_target", "This is the target of a symbolic link.\n"); + do_symlink("stat_target", "stat_symlink", 0); + + cl_must_pass(p_stat("stat_target", &st)); + cl_assert(S_ISREG(st.st_mode)); + cl_assert_equal_i(39, st.st_size); + + cl_must_pass(p_stat("stat_symlink", &st)); + cl_assert(S_ISREG(st.st_mode)); + cl_assert_equal_i(39, st.st_size); +} + +void test_core_link__stat_symlink_directory(void) +{ + struct stat st; + + p_mkdir("stat_dirtarget", 0777); + do_symlink("stat_dirtarget", "stat_dirlink", 1); + + cl_must_pass(p_stat("stat_dirtarget", &st)); + cl_assert(S_ISDIR(st.st_mode)); + + cl_must_pass(p_stat("stat_dirlink", &st)); + cl_assert(S_ISDIR(st.st_mode)); +} + +void test_core_link__stat_symlink_chain(void) +{ + struct stat st; + + cl_git_rewritefile("stat_final_target", "Final target of some symbolic links...\n"); + do_symlink("stat_final_target", "stat_chain_3", 0); + do_symlink("stat_chain_3", "stat_chain_2", 0); + do_symlink("stat_chain_2", "stat_chain_1", 0); + + cl_must_pass(p_stat("stat_chain_1", &st)); + cl_assert(S_ISREG(st.st_mode)); + cl_assert_equal_i(39, st.st_size); +} + +void test_core_link__stat_dangling_symlink(void) +{ + struct stat st; + + do_symlink("stat_nonexistent", "stat_dangling", 0); + + cl_must_fail(p_stat("stat_nonexistent", &st)); + cl_must_fail(p_stat("stat_dangling", &st)); +} + +void test_core_link__stat_dangling_symlink_directory(void) +{ + struct stat st; + + do_symlink("stat_nonexistent", "stat_dangling_dir", 1); + + cl_must_fail(p_stat("stat_nonexistent_dir", &st)); + cl_must_fail(p_stat("stat_dangling", &st)); +} + +void test_core_link__lstat_symlink(void) +{ + git_buf target_path = GIT_BUF_INIT; + struct stat st; + + /* Windows always writes the canonical path as the link target, so + * write the full path on all platforms. + */ + git_buf_join(&target_path, '/', clar_sandbox_path(), "lstat_target"); + + cl_git_rewritefile("lstat_target", "This is the target of a symbolic link.\n"); + do_symlink(git_buf_cstr(&target_path), "lstat_symlink", 0); + + cl_must_pass(p_lstat("lstat_target", &st)); + cl_assert(S_ISREG(st.st_mode)); + cl_assert_equal_i(39, st.st_size); + + cl_must_pass(p_lstat("lstat_symlink", &st)); + cl_assert(S_ISLNK(st.st_mode)); + cl_assert_equal_i(git_buf_len(&target_path), st.st_size); + + git_buf_free(&target_path); +} + +void test_core_link__lstat_symlink_directory(void) +{ + git_buf target_path = GIT_BUF_INIT; + struct stat st; + + git_buf_join(&target_path, '/', clar_sandbox_path(), "lstat_dirtarget"); + + p_mkdir("lstat_dirtarget", 0777); + do_symlink(git_buf_cstr(&target_path), "lstat_dirlink", 1); + + cl_must_pass(p_lstat("lstat_dirtarget", &st)); + cl_assert(S_ISDIR(st.st_mode)); + + cl_must_pass(p_lstat("lstat_dirlink", &st)); + cl_assert(S_ISLNK(st.st_mode)); + cl_assert_equal_i(git_buf_len(&target_path), st.st_size); + + git_buf_free(&target_path); +} + +void test_core_link__lstat_dangling_symlink(void) +{ + struct stat st; + + do_symlink("lstat_nonexistent", "lstat_dangling", 0); + + cl_must_fail(p_lstat("lstat_nonexistent", &st)); + + cl_must_pass(p_lstat("lstat_dangling", &st)); + cl_assert(S_ISLNK(st.st_mode)); + cl_assert_equal_i(strlen("lstat_nonexistent"), st.st_size); +} + +void test_core_link__lstat_dangling_symlink_directory(void) +{ + struct stat st; + + do_symlink("lstat_nonexistent", "lstat_dangling_dir", 1); + + cl_must_fail(p_lstat("lstat_nonexistent", &st)); + + cl_must_pass(p_lstat("lstat_dangling_dir", &st)); + cl_assert(S_ISLNK(st.st_mode)); + cl_assert_equal_i(strlen("lstat_nonexistent"), st.st_size); +} + +void test_core_link__stat_junction(void) +{ +#ifdef GIT_WIN32 + git_buf target_path = GIT_BUF_INIT; + struct stat st; + + git_buf_join(&target_path, '/', clar_sandbox_path(), "stat_junctarget"); + + p_mkdir("stat_junctarget", 0777); + do_junction(git_buf_cstr(&target_path), "stat_junction"); + + cl_must_pass(p_stat("stat_junctarget", &st)); + cl_assert(S_ISDIR(st.st_mode)); + + cl_must_pass(p_stat("stat_junction", &st)); + cl_assert(S_ISDIR(st.st_mode)); + + git_buf_free(&target_path); +#endif +} + +void test_core_link__stat_dangling_junction(void) +{ +#ifdef GIT_WIN32 + git_buf target_path = GIT_BUF_INIT; + struct stat st; + + git_buf_join(&target_path, '/', clar_sandbox_path(), "stat_nonexistent_junctarget"); + + p_mkdir("stat_nonexistent_junctarget", 0777); + do_junction(git_buf_cstr(&target_path), "stat_dangling_junction"); + + RemoveDirectory("stat_nonexistent_junctarget"); + + cl_must_fail(p_stat("stat_nonexistent_junctarget", &st)); + cl_must_fail(p_stat("stat_dangling_junction", &st)); + + git_buf_free(&target_path); +#endif +} + +void test_core_link__lstat_junction(void) +{ +#ifdef GIT_WIN32 + git_buf target_path = GIT_BUF_INIT; + struct stat st; + + git_buf_join(&target_path, '/', clar_sandbox_path(), "lstat_junctarget"); + + p_mkdir("lstat_junctarget", 0777); + do_junction(git_buf_cstr(&target_path), "lstat_junction"); + + cl_must_pass(p_lstat("lstat_junctarget", &st)); + cl_assert(S_ISDIR(st.st_mode)); + + cl_must_pass(p_lstat("lstat_junction", &st)); + cl_assert(S_ISLNK(st.st_mode)); + + git_buf_free(&target_path); +#endif +} + +void test_core_link__lstat_dangling_junction(void) +{ +#ifdef GIT_WIN32 + git_buf target_path = GIT_BUF_INIT; + struct stat st; + + git_buf_join(&target_path, '/', clar_sandbox_path(), "lstat_nonexistent_junctarget"); + + p_mkdir("lstat_nonexistent_junctarget", 0777); + do_junction(git_buf_cstr(&target_path), "lstat_dangling_junction"); + + RemoveDirectory("lstat_nonexistent_junctarget"); + + cl_must_fail(p_lstat("lstat_nonexistent_junctarget", &st)); + + cl_must_pass(p_lstat("lstat_dangling_junction", &st)); + cl_assert(S_ISLNK(st.st_mode)); + cl_assert_equal_i(git_buf_len(&target_path), st.st_size); + + git_buf_free(&target_path); +#endif +} + +void test_core_link__stat_hardlink(void) +{ + struct stat st; + + cl_git_rewritefile("stat_hardlink1", "This file has many names!\n"); + do_hardlink("stat_hardlink1", "stat_hardlink2"); + + cl_must_pass(p_stat("stat_hardlink1", &st)); + cl_assert(S_ISREG(st.st_mode)); + cl_assert_equal_i(26, st.st_size); + + cl_must_pass(p_stat("stat_hardlink2", &st)); + cl_assert(S_ISREG(st.st_mode)); + cl_assert_equal_i(26, st.st_size); +} + +void test_core_link__lstat_hardlink(void) +{ + struct stat st; + + cl_git_rewritefile("lstat_hardlink1", "This file has many names!\n"); + do_hardlink("lstat_hardlink1", "lstat_hardlink2"); + + cl_must_pass(p_lstat("lstat_hardlink1", &st)); + cl_assert(S_ISREG(st.st_mode)); + cl_assert_equal_i(26, st.st_size); + + cl_must_pass(p_lstat("lstat_hardlink2", &st)); + cl_assert(S_ISREG(st.st_mode)); + cl_assert_equal_i(26, st.st_size); +} + +void test_core_link__stat_reparse_point(void) +{ +#ifdef GIT_WIN32 + struct stat st; + + /* Generic reparse points should be treated as regular files, only + * symlinks and junctions should be treated as links. + */ + + cl_git_rewritefile("stat_reparse", "This is a reparse point!\n"); + do_custom_reparse("stat_reparse"); + + cl_must_pass(p_lstat("stat_reparse", &st)); + cl_assert(S_ISREG(st.st_mode)); + cl_assert_equal_i(25, st.st_size); +#endif +} + +void test_core_link__lstat_reparse_point(void) +{ +#ifdef GIT_WIN32 + struct stat st; + + cl_git_rewritefile("lstat_reparse", "This is a reparse point!\n"); + do_custom_reparse("lstat_reparse"); + + cl_must_pass(p_lstat("lstat_reparse", &st)); + cl_assert(S_ISREG(st.st_mode)); + cl_assert_equal_i(25, st.st_size); +#endif +} + +void test_core_link__readlink_nonexistent_file(void) +{ + char buf[2048]; + + cl_must_fail(p_readlink("readlink_nonexistent", buf, 2048)); + cl_assert_equal_i(ENOENT, errno); +} + +void test_core_link__readlink_normal_file(void) +{ + char buf[2048]; + + cl_git_rewritefile("readlink_regfile", "This is a regular file!\n"); + cl_must_fail(p_readlink("readlink_regfile", buf, 2048)); + cl_assert_equal_i(EINVAL, errno); +} + +void test_core_link__readlink_symlink(void) +{ + git_buf target_path = GIT_BUF_INIT; + int len; + char buf[2048]; + + git_buf_join(&target_path, '/', clar_sandbox_path(), "readlink_target"); + + cl_git_rewritefile("readlink_target", "This is the target of a symlink\n"); + do_symlink(git_buf_cstr(&target_path), "readlink_link", 0); + + len = p_readlink("readlink_link", buf, 2048); + cl_must_pass(len); + + buf[len] = 0; + + cl_assert_equal_s(git_buf_cstr(unslashify(&target_path)), buf); + + git_buf_free(&target_path); +} + +void test_core_link__readlink_dangling(void) +{ + git_buf target_path = GIT_BUF_INIT; + int len; + char buf[2048]; + + git_buf_join(&target_path, '/', clar_sandbox_path(), "readlink_nonexistent"); + + do_symlink(git_buf_cstr(&target_path), "readlink_dangling", 0); + + len = p_readlink("readlink_dangling", buf, 2048); + cl_must_pass(len); + + buf[len] = 0; + + cl_assert_equal_s(git_buf_cstr(unslashify(&target_path)), buf); + + git_buf_free(&target_path); +} + +void test_core_link__readlink_multiple(void) +{ + git_buf target_path = GIT_BUF_INIT, + path3 = GIT_BUF_INIT, path2 = GIT_BUF_INIT, path1 = GIT_BUF_INIT; + int len; + char buf[2048]; + + git_buf_join(&target_path, '/', clar_sandbox_path(), "readlink_final"); + git_buf_join(&path3, '/', clar_sandbox_path(), "readlink_3"); + git_buf_join(&path2, '/', clar_sandbox_path(), "readlink_2"); + git_buf_join(&path1, '/', clar_sandbox_path(), "readlink_1"); + + do_symlink(git_buf_cstr(&target_path), git_buf_cstr(&path3), 0); + do_symlink(git_buf_cstr(&path3), git_buf_cstr(&path2), 0); + do_symlink(git_buf_cstr(&path2), git_buf_cstr(&path1), 0); + + len = p_readlink("readlink_1", buf, 2048); + cl_must_pass(len); + + buf[len] = 0; + + cl_assert_equal_s(git_buf_cstr(unslashify(&path2)), buf); + + git_buf_free(&path1); + git_buf_free(&path2); + git_buf_free(&path3); + git_buf_free(&target_path); +} diff --git a/tests/diff/binary.c b/tests/diff/binary.c new file mode 100644 index 000000000..cb574a588 --- /dev/null +++ b/tests/diff/binary.c @@ -0,0 +1,263 @@ +#include "clar_libgit2.h" + +#include "buffer.h" +#include "filebuf.h" + +static git_repository *repo; + +void test_diff_binary__initialize(void) +{ +} + +void test_diff_binary__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_patch( + const char *one, + const char *two, + const git_diff_options *opts, + const char *expected) +{ + git_oid id_one, id_two; + git_index *index = NULL; + git_commit *commit_one, *commit_two = NULL; + git_tree *tree_one, *tree_two; + git_diff *diff; + git_patch *patch; + git_buf actual = GIT_BUF_INIT; + + cl_git_pass(git_oid_fromstr(&id_one, one)); + cl_git_pass(git_commit_lookup(&commit_one, repo, &id_one)); + cl_git_pass(git_commit_tree(&tree_one, commit_one)); + + if (two) { + cl_git_pass(git_oid_fromstr(&id_two, two)); + cl_git_pass(git_commit_lookup(&commit_two, repo, &id_two)); + cl_git_pass(git_commit_tree(&tree_two, commit_two)); + } else { + cl_git_pass(git_repository_index(&index, repo)); + cl_git_pass(git_index_write_tree(&id_two, index)); + cl_git_pass(git_tree_lookup(&tree_two, repo, &id_two)); + } + + cl_git_pass(git_diff_tree_to_tree(&diff, repo, tree_one, tree_two, opts)); + + cl_git_pass(git_patch_from_diff(&patch, diff, 0)); + cl_git_pass(git_patch_to_buf(&actual, patch)); + + cl_assert_equal_s(expected, actual.ptr); + + git_buf_free(&actual); + git_patch_free(patch); + git_diff_free(diff); + git_tree_free(tree_one); + git_tree_free(tree_two); + git_commit_free(commit_one); + git_commit_free(commit_two); + git_index_free(index); +} + +void test_diff_binary__add_normal(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + const char *expected = + "diff --git a/binary.bin b/binary.bin\n" \ + "new file mode 100644\n" \ + "index 0000000..bd474b2\n" \ + "Binary files /dev/null and b/binary.bin differ\n"; + + repo = cl_git_sandbox_init("diff_format_email"); + test_patch( + "873806f6f27e631eb0b23e4b56bea2bfac14a373", + "897d3af16ca9e420cd071b1c4541bd2b91d04c8c", + &opts, + expected); +} + +void test_diff_binary__add(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + const char *expected = + "diff --git a/binary.bin b/binary.bin\n" \ + "new file mode 100644\n" \ + "index 0000000000000000000000000000000000000000..bd474b2519cc15eab801ff851cc7d50f0dee49a1\n" \ + "GIT binary patch\n" \ + "literal 3\n" \ + "Kc${Nk-~s>u4FC%O\n" + "\n" \ + "literal 0\n" \ + "Hc$@<O00001\n"; + + opts.flags = GIT_DIFF_SHOW_BINARY; + opts.id_abbrev = GIT_OID_HEXSZ; + + repo = cl_git_sandbox_init("diff_format_email"); + test_patch( + "873806f6f27e631eb0b23e4b56bea2bfac14a373", + "897d3af16ca9e420cd071b1c4541bd2b91d04c8c", + &opts, + expected); +} + +void test_diff_binary__modify_normal(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + const char *expected = + "diff --git a/binary.bin b/binary.bin\n" \ + "index bd474b2..9ac35ff 100644\n" \ + "Binary files a/binary.bin and b/binary.bin differ\n"; + + repo = cl_git_sandbox_init("diff_format_email"); + test_patch( + "897d3af16ca9e420cd071b1c4541bd2b91d04c8c", + "8d7523f6fcb2404257889abe0d96f093d9f524f9", + &opts, + expected); +} + +void test_diff_binary__modify(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + const char *expected = + "diff --git a/binary.bin b/binary.bin\n" \ + "index bd474b2519cc15eab801ff851cc7d50f0dee49a1..9ac35ff15cd8864aeafd889e4826a3150f0b06c4 100644\n" \ + "GIT binary patch\n" \ + "literal 5\n" \ + "Mc${NkU}WL~000&M4gdfE\n" \ + "\n" \ + "literal 3\n" \ + "Kc${Nk-~s>u4FC%O\n"; + + opts.flags = GIT_DIFF_SHOW_BINARY; + + repo = cl_git_sandbox_init("diff_format_email"); + test_patch( + "897d3af16ca9e420cd071b1c4541bd2b91d04c8c", + "8d7523f6fcb2404257889abe0d96f093d9f524f9", + &opts, + expected); +} + +void test_diff_binary__delete_normal(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + const char *expected = + "diff --git a/binary.bin b/binary.bin\n" \ + "deleted file mode 100644\n" \ + "index bd474b2..0000000\n" \ + "Binary files a/binary.bin and /dev/null differ\n"; + + repo = cl_git_sandbox_init("diff_format_email"); + test_patch( + "897d3af16ca9e420cd071b1c4541bd2b91d04c8c", + "873806f6f27e631eb0b23e4b56bea2bfac14a373", + &opts, + expected); +} + +void test_diff_binary__delete(void) +{ + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + const char *expected = + "diff --git a/binary.bin b/binary.bin\n" \ + "deleted file mode 100644\n" \ + "index bd474b2519cc15eab801ff851cc7d50f0dee49a1..0000000000000000000000000000000000000000\n" \ + "GIT binary patch\n" \ + "literal 0\n" \ + "Hc$@<O00001\n" \ + "\n" \ + "literal 3\n" \ + "Kc${Nk-~s>u4FC%O\n"; + + opts.flags = GIT_DIFF_SHOW_BINARY; + opts.id_abbrev = GIT_OID_HEXSZ; + + repo = cl_git_sandbox_init("diff_format_email"); + test_patch( + "897d3af16ca9e420cd071b1c4541bd2b91d04c8c", + "873806f6f27e631eb0b23e4b56bea2bfac14a373", + &opts, + expected); +} + +void test_diff_binary__delta(void) +{ + git_index *index; + git_buf contents = GIT_BUF_INIT; + size_t i; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + const char *expected = + "diff --git a/songof7cities.txt b/songof7cities.txt\n" \ + "index 4210ffd5c390b21dd5483375e75288dea9ede512..cc84ec183351c9944ed90a619ca08911924055b5 100644\n" \ + "GIT binary patch\n" \ + "delta 198\n" \ + "zc$}LmI8{(0BqLQJI6p64AwNwaIJGP_Pa)Ye#M3o+qJ$<Jl;sX*mF<MGCYv&*L7AHu\n" \ + "zGA1*^gt?gYVN82wTbPO_W)+x<&1+cP;HrPHR>PQ;Y(X&QMK*C5^Br3bjG4d=XI^5@\n" \ + "JfH567LIG)KJdFSV\n" \ + "\n" \ + "delta 198\n" \ + "zc$}LmI8{(0BqLQJI6p64AwNwaIJGP_Pr*5}Br~;mqJ$<Jl;sX*mF<MGCYv&*L7AHu\n" \ + "zGA1*^gt?gYVN82wTbPO_W)+x<&1+cP;HrPHR>PQ;Y(X&QMK*C5^Br3bjG4d=XI^5@\n" \ + "JfH567LIF3FM2!Fd\n"; + + opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY; + opts.id_abbrev = GIT_OID_HEXSZ; + + repo = cl_git_sandbox_init("renames"); + cl_git_pass(git_repository_index(&index, repo)); + + cl_git_pass(git_futils_readbuffer(&contents, "renames/songof7cities.txt")); + + for (i = 0; i < contents.size - 6; i++) { + if (strncmp(&contents.ptr[i], "Cities", 6) == 0) + memcpy(&contents.ptr[i], "cITIES", 6); + } + + cl_git_rewritefile("renames/songof7cities.txt", contents.ptr); + cl_git_pass(git_index_add_bypath(index, "songof7cities.txt")); + cl_git_pass(git_index_write(index)); + + test_patch( + "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13", + NULL, + &opts, + expected); + + git_index_free(index); + git_buf_free(&contents); +} + +void test_diff_binary__delta_append(void) +{ + git_index *index; + git_diff_options opts = GIT_DIFF_OPTIONS_INIT; + const char *expected = + "diff --git a/untimely.txt b/untimely.txt\n" \ + "index 9a69d960ae94b060f56c2a8702545e2bb1abb935..1111d4f11f4b35bf6759e0fb714fe09731ef0840 100644\n" \ + "GIT binary patch\n" \ + "delta 32\n" \ + "nc%1vf+QYWt3zLL@hC)e3Vu?a>QDRl4f_G*?PG(-ZA}<#J$+QbW\n" \ + "\n" \ + "delta 7\n" \ + "Oc%18D`@*{63ljhg(E~C7\n"; + + opts.flags = GIT_DIFF_SHOW_BINARY | GIT_DIFF_FORCE_BINARY; + opts.id_abbrev = GIT_OID_HEXSZ; + + repo = cl_git_sandbox_init("renames"); + cl_git_pass(git_repository_index(&index, repo)); + + cl_git_append2file("renames/untimely.txt", "Oh that crazy Kipling!\r\n"); + cl_git_pass(git_index_add_bypath(index, "untimely.txt")); + cl_git_pass(git_index_write(index)); + + test_patch( + "19dd32dfb1520a64e5bbaae8dce6ef423dfa2f13", + NULL, + &opts, + expected); + + git_index_free(index); +} diff --git a/tests/diff/format_email.c b/tests/diff/format_email.c index 3260fdea8..18ad99bd5 100644 --- a/tests/diff/format_email.c +++ b/tests/diff/format_email.c @@ -17,15 +17,44 @@ void test_diff_format_email__cleanup(void) cl_git_sandbox_cleanup(); } -void test_diff_format_email__simple(void) +static void assert_email_match( + const char *expected, + const char *oidstr, + git_diff_format_email_options *opts) { git_oid oid; git_commit *commit = NULL; git_diff *diff = NULL; - git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT; git_buf buf = GIT_BUF_INIT; - const char *email = + git_oid_fromstr(&oid, oidstr); + + cl_git_pass(git_commit_lookup(&commit, repo, &oid)); + + opts->id = git_commit_id(commit); + opts->author = git_commit_author(commit); + if (!opts->summary) + opts->summary = git_commit_summary(commit); + + cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); + cl_git_pass(git_diff_format_email(&buf, diff, opts)); + + cl_assert_equal_s(expected, git_buf_cstr(&buf)); + git_buf_clear(&buf); + + cl_git_pass(git_diff_commit_as_email( + &buf, repo, commit, 1, 1, opts->flags, NULL)); + cl_assert_equal_s(expected, git_buf_cstr(&buf)); + + git_diff_free(diff); + git_commit_free(commit); + git_buf_free(&buf); +} + +void test_diff_format_email__simple(void) +{ + git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT; + const char *email = "From 9264b96c6d104d0e07ae33d3007b6a48246c6f92 Mon Sep 17 00:00:00 2001\n" \ "From: Jacques Germishuys <jacquesg@striata.com>\n" \ "Date: Wed, 9 Apr 2014 20:57:01 +0200\n" \ @@ -64,25 +93,8 @@ void test_diff_format_email__simple(void) "libgit2 " LIBGIT2_VERSION "\n" \ "\n"; - git_oid_fromstr(&oid, "9264b96c6d104d0e07ae33d3007b6a48246c6f92"); - - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - - opts.id = git_commit_id(commit); - opts.author = git_commit_author(commit); - opts.summary = git_commit_summary(commit); - - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); - cl_git_pass(git_diff_format_email(&buf, diff, &opts)); - cl_assert(strcmp(git_buf_cstr(&buf), email) == 0); - - git_buf_clear(&buf); - cl_git_pass(git_diff_commit_as_email(&buf, repo, commit, 1, 1, 0, NULL)); - cl_assert(strcmp(git_buf_cstr(&buf), email) == 0); - - git_diff_free(diff); - git_commit_free(commit); - git_buf_free(&buf); + assert_email_match( + email, "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts); } void test_diff_format_email__multiple(void) @@ -90,10 +102,10 @@ void test_diff_format_email__multiple(void) git_oid oid; git_commit *commit = NULL; git_diff *diff = NULL; - git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT; + git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT; git_buf buf = GIT_BUF_INIT; - const char *email = + const char *email = "From 10808fe9c9be5a190c0ba68d1a002233fb363508 Mon Sep 17 00:00:00 2001\n" \ "From: Jacques Germishuys <jacquesg@striata.com>\n" \ "Date: Thu, 10 Apr 2014 19:37:05 +0200\n" \ @@ -167,6 +179,7 @@ void test_diff_format_email__multiple(void) "libgit2 " LIBGIT2_VERSION "\n" \ "\n"; + git_oid_fromstr(&oid, "10808fe9c9be5a190c0ba68d1a002233fb363508"); cl_git_pass(git_commit_lookup(&commit, repo, &oid)); @@ -196,7 +209,7 @@ void test_diff_format_email__multiple(void) cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); cl_git_pass(git_diff_format_email(&buf, diff, &opts)); - cl_assert(strcmp(git_buf_cstr(&buf), email) == 0); + cl_assert_equal_s(email, git_buf_cstr(&buf)); git_diff_free(diff); git_commit_free(commit); @@ -205,13 +218,8 @@ void test_diff_format_email__multiple(void) void test_diff_format_email__exclude_marker(void) { - git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT; - git_buf buf = GIT_BUF_INIT; - - const char *email = + const char *email = "From 9264b96c6d104d0e07ae33d3007b6a48246c6f92 Mon Sep 17 00:00:00 2001\n" \ "From: Jacques Germishuys <jacquesg@striata.com>\n" \ "Date: Wed, 9 Apr 2014 20:57:01 +0200\n" \ @@ -250,27 +258,10 @@ void test_diff_format_email__exclude_marker(void) "libgit2 " LIBGIT2_VERSION "\n" \ "\n"; - git_oid_fromstr(&oid, "9264b96c6d104d0e07ae33d3007b6a48246c6f92"); - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - - opts.id = git_commit_id(commit); - opts.author = git_commit_author(commit); - opts.summary = git_commit_summary(commit); - opts.flags |= GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER; - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); - cl_git_pass(git_diff_format_email(&buf, diff, &opts)); - cl_assert(strcmp(git_buf_cstr(&buf), email) == 0); - - git_buf_clear(&buf); - cl_git_pass(git_diff_commit_as_email(&buf, repo, commit, 1, 1, - GIT_DIFF_FORMAT_EMAIL_EXCLUDE_SUBJECT_PATCH_MARKER, NULL)); - cl_assert(strcmp(git_buf_cstr(&buf), email) == 0); - - git_diff_free(diff); - git_commit_free(commit); - git_buf_free(&buf); + assert_email_match( + email, "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts); } void test_diff_format_email__invalid_no(void) @@ -303,13 +294,8 @@ void test_diff_format_email__invalid_no(void) void test_diff_format_email__mode_change(void) { - git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT; - git_buf buf = GIT_BUF_INIT; - - const char *email = + const char *email = "From 7ade76dd34bba4733cf9878079f9fd4a456a9189 Mon Sep 17 00:00:00 2001\n" \ "From: Jacques Germishuys <jacquesg@striata.com>\n" \ "Date: Thu, 10 Apr 2014 10:05:03 +0200\n" \ @@ -330,36 +316,14 @@ void test_diff_format_email__mode_change(void) "libgit2 " LIBGIT2_VERSION "\n" \ "\n"; - git_oid_fromstr(&oid, "7ade76dd34bba4733cf9878079f9fd4a456a9189"); - - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - - opts.id = git_commit_id(commit); - opts.author = git_commit_author(commit); - opts.summary = git_commit_summary(commit); - - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); - cl_git_pass(git_diff_format_email(&buf, diff, &opts)); - cl_assert(strcmp(git_buf_cstr(&buf), email) == 0); - - git_buf_clear(&buf); - cl_git_pass(git_diff_commit_as_email(&buf, repo, commit, 1, 1, 0, NULL)); - cl_assert(strcmp(git_buf_cstr(&buf), email) == 0); - - git_diff_free(diff); - git_commit_free(commit); - git_buf_free(&buf); + assert_email_match( + email, "7ade76dd34bba4733cf9878079f9fd4a456a9189", &opts); } void test_diff_format_email__rename_add_remove(void) { - git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT; - git_buf buf = GIT_BUF_INIT; - - const char *email = + const char *email = "From 6e05acc5a5dab507d91a0a0cc0fb05a3dd98892d Mon Sep 17 00:00:00 2001\n" \ "From: Jacques Germishuys <jacquesg@striata.com>\n" \ "Date: Wed, 9 Apr 2014 21:15:56 +0200\n" \ @@ -422,35 +386,13 @@ void test_diff_format_email__rename_add_remove(void) "libgit2 " LIBGIT2_VERSION "\n" \ "\n"; - git_oid_fromstr(&oid, "6e05acc5a5dab507d91a0a0cc0fb05a3dd98892d"); - - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - - opts.id = git_commit_id(commit); - opts.author = git_commit_author(commit); - opts.summary = git_commit_summary(commit); - - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); - cl_git_pass(git_diff_format_email(&buf, diff, &opts)); - cl_assert(strcmp(git_buf_cstr(&buf), email) == 0); - - git_buf_clear(&buf); - cl_git_pass(git_diff_commit_as_email(&buf, repo, commit, 1, 1, 0, NULL)); - cl_assert(strcmp(git_buf_cstr(&buf), email) == 0); - - git_diff_free(diff); - git_commit_free(commit); - git_buf_free(&buf); + assert_email_match( + email, "6e05acc5a5dab507d91a0a0cc0fb05a3dd98892d", &opts); } void test_diff_format_email__multiline_summary(void) { - git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT; - git_buf buf = GIT_BUF_INIT; - const char *email = "From 9264b96c6d104d0e07ae33d3007b6a48246c6f92 Mon Sep 17 00:00:00 2001\n" \ "From: Jacques Germishuys <jacquesg@striata.com>\n" \ @@ -490,36 +432,15 @@ void test_diff_format_email__multiline_summary(void) "libgit2 " LIBGIT2_VERSION "\n" \ "\n"; - git_oid_fromstr(&oid, "9264b96c6d104d0e07ae33d3007b6a48246c6f92"); - - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - - opts.id = git_commit_id(commit); - opts.author = git_commit_author(commit); opts.summary = "Modify some content\nSome extra stuff here"; - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); - cl_git_pass(git_diff_format_email(&buf, diff, &opts)); - cl_assert(strcmp(git_buf_cstr(&buf), email) == 0); - - git_buf_clear(&buf); - cl_git_pass(git_diff_commit_as_email(&buf, repo, commit, 1, 1, 0, NULL)); - cl_assert(strcmp(git_buf_cstr(&buf), email) == 0); - - git_diff_free(diff); - git_commit_free(commit); - git_buf_free(&buf); + assert_email_match( + email, "9264b96c6d104d0e07ae33d3007b6a48246c6f92", &opts); } void test_diff_format_email__binary(void) { - git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; git_diff_format_email_options opts = GIT_DIFF_FORMAT_EMAIL_OPTIONS_INIT; - git_buf buf = GIT_BUF_INIT; - - /* TODO: Actually 0 bytes here should be 5!. Seems like we don't load the new content for binary files? */ const char *email = "From 8d7523f6fcb2404257889abe0d96f093d9f524f9 Mon Sep 17 00:00:00 2001\n" \ "From: Jacques Germishuys <jacquesg@striata.com>\n" \ @@ -536,21 +457,11 @@ void test_diff_format_email__binary(void) "--\n" \ "libgit2 " LIBGIT2_VERSION "\n" \ "\n"; + /* TODO: Actually 0 bytes here should be 5!. Seems like we don't load the new content for binary files? */ - git_oid_fromstr(&oid, "8d7523f6fcb2404257889abe0d96f093d9f524f9"); - - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - - opts.id = git_commit_id(commit); - opts.author = git_commit_author(commit); opts.summary = "Modified binary file"; - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); - cl_git_pass(git_diff_format_email(&buf, diff, &opts)); - cl_assert(strcmp(git_buf_cstr(&buf), email) == 0); - - git_diff_free(diff); - git_commit_free(commit); - git_buf_free(&buf); + assert_email_match( + email, "8d7523f6fcb2404257889abe0d96f093d9f524f9", &opts); } diff --git a/tests/diff/patch.c b/tests/diff/patch.c index 76d7fcde3..1184d1968 100644 --- a/tests/diff/patch.c +++ b/tests/diff/patch.c @@ -2,6 +2,7 @@ #include "git2/sys/repository.h" #include "diff_helpers.h" +#include "diff.h" #include "repository.h" #include "buf_text.h" diff --git a/tests/diff/stats.c b/tests/diff/stats.c index 131b7681d..055019f69 100644 --- a/tests/diff/stats.c +++ b/tests/diff/stats.c @@ -5,246 +5,173 @@ #include "commit.h" #include "diff.h" -static git_repository *repo; +static git_repository *_repo; +static git_diff_stats *_stats; void test_diff_stats__initialize(void) { - repo = cl_git_sandbox_init("diff_format_email"); + _repo = cl_git_sandbox_init("diff_format_email"); } void test_diff_stats__cleanup(void) { + git_diff_stats_free(_stats); _stats = NULL; cl_git_sandbox_cleanup(); } -void test_diff_stats__stat(void) +static void diff_stats_from_commit_oid( + git_diff_stats **stats, const char *oidstr, bool rename) { git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; - git_diff_stats *stats = NULL; - git_buf buf = GIT_BUF_INIT; + git_commit *commit; + git_diff *diff; + + git_oid_fromstr(&oid, oidstr); + cl_git_pass(git_commit_lookup(&commit, _repo, &oid)); + cl_git_pass(git_diff__commit(&diff, _repo, commit, NULL)); + if (rename) + cl_git_pass(git_diff_find_similar(diff, NULL)); + cl_git_pass(git_diff_get_stats(stats, diff)); + + git_diff_free(diff); + git_commit_free(commit); +} +void test_diff_stats__stat(void) +{ + git_buf buf = GIT_BUF_INIT; const char *stat = " file1.txt | 8 +++++---\n" \ " 1 file changed, 5 insertions(+), 3 deletions(-)\n"; - git_oid_fromstr(&oid, "9264b96c6d104d0e07ae33d3007b6a48246c6f92"); + diff_stats_from_commit_oid( + &_stats, "9264b96c6d104d0e07ae33d3007b6a48246c6f92", false); - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); + cl_assert_equal_sz(1, git_diff_stats_files_changed(_stats)); + cl_assert_equal_sz(5, git_diff_stats_insertions(_stats)); + cl_assert_equal_sz(3, git_diff_stats_deletions(_stats)); - cl_git_pass(git_diff_get_stats(&stats, diff)); - cl_assert(git_diff_stats_files_changed(stats) == 1); - cl_assert(git_diff_stats_insertions(stats) == 5); - cl_assert(git_diff_stats_deletions(stats) == 3); - - cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL)); + cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0)); cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0); - - git_diff_stats_free(stats); - git_diff_free(diff); - git_commit_free(commit); git_buf_free(&buf); } void test_diff_stats__multiple_hunks(void) { - git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; - git_diff_stats *stats = NULL; git_buf buf = GIT_BUF_INIT; - const char *stat = " file2.txt | 5 +++--\n" \ " file3.txt | 6 ++++--\n" \ " 2 files changed, 7 insertions(+), 4 deletions(-)\n"; - git_oid_fromstr(&oid, "cd471f0d8770371e1bc78bcbb38db4c7e4106bd2"); - - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); + diff_stats_from_commit_oid( + &_stats, "cd471f0d8770371e1bc78bcbb38db4c7e4106bd2", false); - cl_git_pass(git_diff_get_stats(&stats, diff)); - cl_assert(git_diff_stats_files_changed(stats) == 2); - cl_assert(git_diff_stats_insertions(stats) == 7); - cl_assert(git_diff_stats_deletions(stats) == 4); + cl_assert_equal_sz(2, git_diff_stats_files_changed(_stats)); + cl_assert_equal_sz(7, git_diff_stats_insertions(_stats)); + cl_assert_equal_sz(4, git_diff_stats_deletions(_stats)); - cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL)); - cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0); - - git_diff_stats_free(stats); - git_diff_free(diff); - git_commit_free(commit); + cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0)); + cl_assert_equal_s(stat, git_buf_cstr(&buf)); git_buf_free(&buf); } void test_diff_stats__numstat(void) { - git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; - git_diff_stats *stats = NULL; git_buf buf = GIT_BUF_INIT; - const char *stat = "3 2 file2.txt\n" "4 2 file3.txt\n"; - git_oid_fromstr(&oid, "cd471f0d8770371e1bc78bcbb38db4c7e4106bd2"); - - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); - - cl_git_pass(git_diff_get_stats(&stats, diff)); - - cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_NUMBER)); - cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0); + diff_stats_from_commit_oid( + &_stats, "cd471f0d8770371e1bc78bcbb38db4c7e4106bd2", false); - git_diff_stats_free(stats); - git_diff_free(diff); - git_commit_free(commit); + cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_NUMBER, 0)); + cl_assert_equal_s(stat, git_buf_cstr(&buf)); git_buf_free(&buf); } void test_diff_stats__shortstat(void) { - git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; - git_diff_stats *stats = NULL; git_buf buf = GIT_BUF_INIT; - const char *stat = " 1 file changed, 5 insertions(+), 3 deletions(-)\n"; - git_oid_fromstr(&oid, "9264b96c6d104d0e07ae33d3007b6a48246c6f92"); - - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); + diff_stats_from_commit_oid( + &_stats, "9264b96c6d104d0e07ae33d3007b6a48246c6f92", false); - cl_git_pass(git_diff_get_stats(&stats, diff)); - cl_assert(git_diff_stats_files_changed(stats) == 1); - cl_assert(git_diff_stats_insertions(stats) == 5); - cl_assert(git_diff_stats_deletions(stats) == 3); + cl_assert_equal_sz(1, git_diff_stats_files_changed(_stats)); + cl_assert_equal_sz(5, git_diff_stats_insertions(_stats)); + cl_assert_equal_sz(3, git_diff_stats_deletions(_stats)); - cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_SHORT)); - cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0); - - git_diff_stats_free(stats); - git_diff_free(diff); - git_commit_free(commit); + cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_SHORT, 0)); + cl_assert_equal_s(stat, git_buf_cstr(&buf)); git_buf_free(&buf); } void test_diff_stats__rename(void) { - git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; - git_diff_stats *stats = NULL; git_buf buf = GIT_BUF_INIT; - const char *stat = " file2.txt => file2.txt.renamed | 1 +\n" " file3.txt => file3.txt.renamed | 4 +++-\n" - " 2 files changed, 4 insertions(+), 1 deletions(-)\n"; - - git_oid_fromstr(&oid, "8947a46e2097638ca6040ad4877246f4186ec3bd"); + " 2 files changed, 4 insertions(+), 1 deletion(-)\n"; - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); - cl_git_pass(git_diff_find_similar(diff, NULL)); + diff_stats_from_commit_oid( + &_stats, "8947a46e2097638ca6040ad4877246f4186ec3bd", true); - cl_git_pass(git_diff_get_stats(&stats, diff)); - cl_assert(git_diff_stats_files_changed(stats) == 2); - cl_assert(git_diff_stats_insertions(stats) == 4); - cl_assert(git_diff_stats_deletions(stats) == 1); + cl_assert_equal_sz(2, git_diff_stats_files_changed(_stats)); + cl_assert_equal_sz(4, git_diff_stats_insertions(_stats)); + cl_assert_equal_sz(1, git_diff_stats_deletions(_stats)); - cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL)); - cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0); - - git_diff_stats_free(stats); - git_diff_free(diff); - git_commit_free(commit); + cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0)); + cl_assert_equal_s(stat, git_buf_cstr(&buf)); git_buf_free(&buf); } void test_diff_stats__rename_nochanges(void) { - git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; - git_diff_stats *stats = NULL; git_buf buf = GIT_BUF_INIT; - const char *stat = " file2.txt.renamed => file2.txt.renamed2 | 0\n" " file3.txt.renamed => file3.txt.renamed2 | 0\n" " 2 files changed, 0 insertions(+), 0 deletions(-)\n"; - git_oid_fromstr(&oid, "3991dce9e71a0641ca49a6a4eea6c9e7ff402ed4"); - - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); - cl_git_pass(git_diff_find_similar(diff, NULL)); + diff_stats_from_commit_oid( + &_stats, "3991dce9e71a0641ca49a6a4eea6c9e7ff402ed4", true); - cl_git_pass(git_diff_get_stats(&stats, diff)); - cl_assert(git_diff_stats_files_changed(stats) == 2); - cl_assert(git_diff_stats_insertions(stats) == 0); - cl_assert(git_diff_stats_deletions(stats) == 0); + cl_assert_equal_sz(2, git_diff_stats_files_changed(_stats)); + cl_assert_equal_sz(0, git_diff_stats_insertions(_stats)); + cl_assert_equal_sz(0, git_diff_stats_deletions(_stats)); - cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL)); - cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0); - - git_diff_stats_free(stats); - git_diff_free(diff); - git_commit_free(commit); + cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0)); + cl_assert_equal_s(stat, git_buf_cstr(&buf)); git_buf_free(&buf); } void test_diff_stats__rename_and_modifiy(void) { - git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; - git_diff_stats *stats = NULL; git_buf buf = GIT_BUF_INIT; - const char *stat = " file2.txt.renamed2 | 2 +-\n" " file3.txt.renamed2 => file3.txt.renamed | 0\n" - " 2 files changed, 1 insertions(+), 1 deletions(-)\n"; + " 2 files changed, 1 insertion(+), 1 deletion(-)\n"; - git_oid_fromstr(&oid, "4ca10087e696d2ba78d07b146a118e9a7096ed4f"); + diff_stats_from_commit_oid( + &_stats, "4ca10087e696d2ba78d07b146a118e9a7096ed4f", true); - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); - cl_git_pass(git_diff_find_similar(diff, NULL)); + cl_assert_equal_sz(2, git_diff_stats_files_changed(_stats)); + cl_assert_equal_sz(1, git_diff_stats_insertions(_stats)); + cl_assert_equal_sz(1, git_diff_stats_deletions(_stats)); - cl_git_pass(git_diff_get_stats(&stats, diff)); - cl_assert(git_diff_stats_files_changed(stats) == 2); - cl_assert(git_diff_stats_insertions(stats) == 1); - cl_assert(git_diff_stats_deletions(stats) == 1); - - cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL)); - cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0); - - git_diff_stats_free(stats); - git_diff_free(diff); - git_commit_free(commit); + cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0)); + cl_assert_equal_s(stat, git_buf_cstr(&buf)); git_buf_free(&buf); } void test_diff_stats__rename_no_find(void) { - git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; - git_diff_stats *stats = NULL; git_buf buf = GIT_BUF_INIT; - const char *stat = " file2.txt | 5 -----\n" " file2.txt.renamed | 6 ++++++\n" @@ -252,33 +179,21 @@ void test_diff_stats__rename_no_find(void) " file3.txt.renamed | 7 +++++++\n" " 4 files changed, 13 insertions(+), 10 deletions(-)\n"; - git_oid_fromstr(&oid, "8947a46e2097638ca6040ad4877246f4186ec3bd"); + diff_stats_from_commit_oid( + &_stats, "8947a46e2097638ca6040ad4877246f4186ec3bd", false); - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); + cl_assert_equal_sz(4, git_diff_stats_files_changed(_stats)); + cl_assert_equal_sz(13, git_diff_stats_insertions(_stats)); + cl_assert_equal_sz(10, git_diff_stats_deletions(_stats)); - cl_git_pass(git_diff_get_stats(&stats, diff)); - cl_assert(git_diff_stats_files_changed(stats) == 4); - cl_assert(git_diff_stats_insertions(stats) == 13); - cl_assert(git_diff_stats_deletions(stats) == 10); - - cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL)); - cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0); - - git_diff_stats_free(stats); - git_diff_free(diff); - git_commit_free(commit); + cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0)); + cl_assert_equal_s(stat, git_buf_cstr(&buf)); git_buf_free(&buf); } void test_diff_stats__rename_nochanges_no_find(void) { - git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; - git_diff_stats *stats = NULL; git_buf buf = GIT_BUF_INIT; - const char *stat = " file2.txt.renamed | 6 ------\n" " file2.txt.renamed2 | 6 ++++++\n" @@ -286,143 +201,85 @@ void test_diff_stats__rename_nochanges_no_find(void) " file3.txt.renamed2 | 7 +++++++\n" " 4 files changed, 13 insertions(+), 13 deletions(-)\n"; - git_oid_fromstr(&oid, "3991dce9e71a0641ca49a6a4eea6c9e7ff402ed4"); - - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); + diff_stats_from_commit_oid( + &_stats, "3991dce9e71a0641ca49a6a4eea6c9e7ff402ed4", false); - cl_git_pass(git_diff_get_stats(&stats, diff)); - cl_assert(git_diff_stats_files_changed(stats) == 4); - cl_assert(git_diff_stats_insertions(stats) == 13); - cl_assert(git_diff_stats_deletions(stats) == 13); - - cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL)); - cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0); + cl_assert_equal_sz(4, git_diff_stats_files_changed(_stats)); + cl_assert_equal_sz(13, git_diff_stats_insertions(_stats)); + cl_assert_equal_sz(13, git_diff_stats_deletions(_stats)); - git_diff_stats_free(stats); - git_diff_free(diff); - git_commit_free(commit); + cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0)); + cl_assert_equal_s(stat, git_buf_cstr(&buf)); git_buf_free(&buf); } void test_diff_stats__rename_and_modifiy_no_find(void) { - git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; - git_diff_stats *stats = NULL; git_buf buf = GIT_BUF_INIT; - const char *stat = " file2.txt.renamed2 | 2 +-\n" " file3.txt.renamed | 7 +++++++\n" " file3.txt.renamed2 | 7 -------\n" " 3 files changed, 8 insertions(+), 8 deletions(-)\n"; - git_oid_fromstr(&oid, "4ca10087e696d2ba78d07b146a118e9a7096ed4f"); - - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); - - cl_git_pass(git_diff_get_stats(&stats, diff)); - cl_assert(git_diff_stats_files_changed(stats) == 3); - cl_assert(git_diff_stats_insertions(stats) == 8); - cl_assert(git_diff_stats_deletions(stats) == 8); + diff_stats_from_commit_oid( + &_stats, "4ca10087e696d2ba78d07b146a118e9a7096ed4f", false); - cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL)); - cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0); + cl_assert_equal_sz(3, git_diff_stats_files_changed(_stats)); + cl_assert_equal_sz(8, git_diff_stats_insertions(_stats)); + cl_assert_equal_sz(8, git_diff_stats_deletions(_stats)); - git_diff_stats_free(stats); - git_diff_free(diff); - git_commit_free(commit); + cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0)); + cl_assert_equal_s(stat, git_buf_cstr(&buf)); git_buf_free(&buf); } void test_diff_stats__binary(void) { - git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; - git_diff_stats *stats = NULL; git_buf buf = GIT_BUF_INIT; - - /* TODO: Actually 0 bytes here should be 5!. Seems like we don't load the new content for binary files? */ const char *stat = " binary.bin | Bin 3 -> 0 bytes\n" " 1 file changed, 0 insertions(+), 0 deletions(-)\n"; + /* TODO: Actually 0 bytes here should be 5!. Seems like we don't load the new content for binary files? */ - git_oid_fromstr(&oid, "8d7523f6fcb2404257889abe0d96f093d9f524f9"); - - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); - - cl_git_pass(git_diff_get_stats(&stats, diff)); - cl_assert(git_diff_stats_files_changed(stats) == 1); - cl_assert(git_diff_stats_insertions(stats) == 0); - cl_assert(git_diff_stats_deletions(stats) == 0); + diff_stats_from_commit_oid( + &_stats, "8d7523f6fcb2404257889abe0d96f093d9f524f9", false); - cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL)); - cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0); + cl_assert_equal_sz(1, git_diff_stats_files_changed(_stats)); + cl_assert_equal_sz(0, git_diff_stats_insertions(_stats)); + cl_assert_equal_sz(0, git_diff_stats_deletions(_stats)); - git_diff_stats_free(stats); - git_diff_free(diff); - git_commit_free(commit); + cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL, 0)); + cl_assert_equal_s(stat, git_buf_cstr(&buf)); git_buf_free(&buf); } void test_diff_stats__binary_numstat(void) { - git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; - git_diff_stats *stats = NULL; git_buf buf = GIT_BUF_INIT; - const char *stat = "- - binary.bin\n"; - git_oid_fromstr(&oid, "8d7523f6fcb2404257889abe0d96f093d9f524f9"); - - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); - - cl_git_pass(git_diff_get_stats(&stats, diff)); + diff_stats_from_commit_oid( + &_stats, "8d7523f6fcb2404257889abe0d96f093d9f524f9", false); - cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_NUMBER)); - cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0); - - git_diff_stats_free(stats); - git_diff_free(diff); - git_commit_free(commit); + cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_NUMBER, 0)); + cl_assert_equal_s(stat, git_buf_cstr(&buf)); git_buf_free(&buf); } void test_diff_stats__mode_change(void) { - git_oid oid; - git_commit *commit = NULL; - git_diff *diff = NULL; - git_diff_stats *stats = NULL; git_buf buf = GIT_BUF_INIT; - const char *stat = " file1.txt.renamed | 0\n" \ " 1 file changed, 0 insertions(+), 0 deletions(-)\n" \ - " mode change 100644 => 100755 file1.txt.renamed\n" \ - "\n"; + " mode change 100644 => 100755 file1.txt.renamed\n"; - git_oid_fromstr(&oid, "7ade76dd34bba4733cf9878079f9fd4a456a9189"); + diff_stats_from_commit_oid( + &_stats, "7ade76dd34bba4733cf9878079f9fd4a456a9189", false); - cl_git_pass(git_commit_lookup(&commit, repo, &oid)); - cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); - - cl_git_pass(git_diff_get_stats(&stats, diff)); - - cl_git_pass(git_diff_stats_to_buf(&buf, stats, GIT_DIFF_STATS_FULL | GIT_DIFF_STATS_INCLUDE_SUMMARY)); - cl_assert(strcmp(git_buf_cstr(&buf), stat) == 0); - - git_diff_stats_free(stats); - git_diff_free(diff); - git_commit_free(commit); + cl_git_pass(git_diff_stats_to_buf(&buf, _stats, GIT_DIFF_STATS_FULL | GIT_DIFF_STATS_INCLUDE_SUMMARY, 0)); + cl_assert_equal_s(stat, git_buf_cstr(&buf)); git_buf_free(&buf); } diff --git a/tests/fetchhead/fetchhead_data.h b/tests/fetchhead/fetchhead_data.h index 34adb3d08..94402abd5 100644 --- a/tests/fetchhead/fetchhead_data.h +++ b/tests/fetchhead/fetchhead_data.h @@ -28,3 +28,6 @@ #define FETCH_HEAD_EXPLICIT_DATA \ "0966a434eb1a025db6b71485ab63a3bfbea520b6\t\tbranch 'first-merge' of git://github.com/libgit2/TestGitRepository\n" + +#define FETCH_HEAD_QUOTE_DATA \ + "0966a434eb1a025db6b71485ab63a3bfbea520b6\t\tbranch 'first's-merge' of git://github.com/libgit2/TestGitRepository\n" diff --git a/tests/fetchhead/nonetwork.c b/tests/fetchhead/nonetwork.c index d8c70e8b2..e7ff2ca30 100644 --- a/tests/fetchhead/nonetwork.c +++ b/tests/fetchhead/nonetwork.c @@ -343,3 +343,12 @@ void test_fetchhead_nonetwork__unborn_with_upstream(void) git_repository_free(repo); cl_fixture_cleanup("./repowithunborn"); } + +void test_fetchhead_nonetwork__quote_in_branch_name(void) +{ + cl_set_cleanup(&cleanup_repository, "./test1"); + cl_git_pass(git_repository_init(&g_repo, "./test1", 0)); + + cl_git_rewritefile("./test1/.git/FETCH_HEAD", FETCH_HEAD_QUOTE_DATA); + cl_git_pass(git_repository_fetchhead_foreach(g_repo, read_noop, NULL)); +} diff --git a/tests/merge/workdir/dirty.c b/tests/merge/workdir/dirty.c index 1d596c51a..776e4ea69 100644 --- a/tests/merge/workdir/dirty.c +++ b/tests/merge/workdir/dirty.c @@ -86,7 +86,7 @@ static void set_core_autocrlf_to(git_repository *repo, bool value) git_config_free(cfg); } -static int merge_branch(int merge_file_favor, int checkout_strategy) +static int merge_branch(void) { git_oid their_oids[1]; git_merge_head *their_heads[1]; @@ -97,8 +97,7 @@ static int merge_branch(int merge_file_favor, int checkout_strategy) cl_git_pass(git_oid_fromstr(&their_oids[0], MERGE_BRANCH_OID)); cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0])); - merge_opts.file_favor = merge_file_favor; - checkout_opts.checkout_strategy = checkout_strategy; + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_ALLOW_CONFLICTS; error = git_merge(repo, (const git_merge_head **)their_heads, 1, &merge_opts, &checkout_opts); git_merge_head_free(their_heads[0]); @@ -214,7 +213,7 @@ static int merge_dirty_files(char *dirty_files[]) write_files(dirty_files); - error = merge_branch(0, 0); + error = merge_branch(); git_object_free(head_object); git_reference_free(head); @@ -237,7 +236,7 @@ static int merge_differently_filtered_files(char *files[]) cl_git_pass(git_index_write(repo_index)); - error = merge_branch(0, 0); + error = merge_branch(); git_object_free(head_object); git_reference_free(head); @@ -248,7 +247,7 @@ static int merge_differently_filtered_files(char *files[]) static int merge_staged_files(char *staged_files[]) { stage_random_files(staged_files); - return merge_branch(0, 0); + return merge_branch(); } void test_merge_workdir_dirty__unaffected_dirty_files_allowed(void) @@ -260,6 +259,23 @@ void test_merge_workdir_dirty__unaffected_dirty_files_allowed(void) cl_git_pass(merge_dirty_files(files)); } +void test_merge_workdir_dirty__unstaged_deletes_maintained(void) +{ + git_reference *head; + git_object *head_object; + + cl_git_pass(git_repository_head(&head, repo)); + cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJ_COMMIT)); + cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD, NULL, NULL)); + + cl_git_pass(p_unlink("merge-resolve/unchanged.txt")); + + cl_git_pass(merge_branch()); + + git_object_free(head_object); + git_reference_free(head); +} + void test_merge_workdir_dirty__affected_dirty_files_disallowed(void) { char **files; @@ -292,7 +308,7 @@ void test_merge_workdir_dirty__identical_staged_files_allowed(void) stage_content(content); git_index_write(repo_index); - cl_git_pass(merge_branch(0, 0)); + cl_git_pass(merge_branch()); } } diff --git a/tests/merge/workdir/simple.c b/tests/merge/workdir/simple.c index cf5b16e7a..327408dc9 100644 --- a/tests/merge/workdir/simple.c +++ b/tests/merge/workdir/simple.c @@ -92,7 +92,7 @@ void test_merge_workdir_simple__cleanup(void) cl_git_sandbox_cleanup(); } -static void merge_simple_branch(int merge_file_favor, int checkout_strategy) +static void merge_simple_branch(int merge_file_favor, int addl_checkout_strategy) { git_oid their_oids[1]; git_merge_head *their_heads[1]; @@ -103,7 +103,9 @@ static void merge_simple_branch(int merge_file_favor, int checkout_strategy) cl_git_pass(git_merge_head_from_id(&their_heads[0], repo, &their_oids[0])); merge_opts.file_favor = merge_file_favor; - checkout_opts.checkout_strategy = checkout_strategy; + checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_ALLOW_CONFLICTS | + addl_checkout_strategy; + cl_git_pass(git_merge(repo, (const git_merge_head **)their_heads, 1, &merge_opts, &checkout_opts)); git_merge_head_free(their_heads[0]); diff --git a/tests/reset/default.c b/tests/reset/default.c index 57a3f7c51..ecb3e7f9f 100644 --- a/tests/reset/default.c +++ b/tests/reset/default.c @@ -21,7 +21,6 @@ static void initialize(const char *repo_name) void test_reset_default__initialize(void) { - initialize("status"); } void test_reset_default__cleanup(void) @@ -67,6 +66,8 @@ void test_reset_default__resetting_filepaths_against_a_null_target_removes_them_ { char *paths[] = { "staged_changes", "staged_new_file" }; + initialize("status"); + _pathspecs.strings = paths; _pathspecs.count = 2; @@ -102,6 +103,8 @@ void test_reset_default__resetting_filepaths_replaces_their_corresponding_index_ char *after_shas[] = { "32504b727382542f9f089e24fddac5e78533e96c", "061d42a44cacde5726057b67558821d95db96f19" }; + initialize("status"); + _pathspecs.strings = paths; _pathspecs.count = 2; before.strings = before_shas; @@ -139,7 +142,6 @@ void test_reset_default__resetting_filepaths_clears_previous_conflicts(void) char *paths[] = { "conflicts-one.txt" }; char *after_shas[] = { "1f85ca51b8e0aac893a621b61a9c2661d6aa6d81" }; - test_reset_default__cleanup(); initialize("mergedrepo"); _pathspecs.strings = paths; @@ -168,6 +170,8 @@ void test_reset_default__resetting_unknown_filepaths_does_not_fail(void) { char *paths[] = { "I_am_not_there.txt", "me_neither.txt" }; + initialize("status"); + _pathspecs.strings = paths; _pathspecs.count = 2; @@ -178,3 +182,34 @@ void test_reset_default__resetting_unknown_filepaths_does_not_fail(void) assert_content_in_index(&_pathspecs, false, NULL); } + +void test_reset_default__staged_rename_reset_delete(void) +{ + git_index *idx; + git_index_entry entry; + const git_index_entry *existing; + char *paths[] = { "new.txt" }; + + initialize("testrepo2"); + + cl_git_pass(git_repository_index(&idx, _repo)); + + existing = git_index_get_bypath(idx, "new.txt", 0); + cl_assert(existing); + memcpy(&entry, existing, sizeof(entry)); + + cl_git_pass(git_index_remove_bypath(idx, "new.txt")); + + entry.path = "renamed.txt"; + cl_git_pass(git_index_add(idx, &entry)); + + _pathspecs.strings = paths; + _pathspecs.count = 1; + + assert_content_in_index(&_pathspecs, false, NULL); + + cl_git_pass(git_revparse_single(&_target, _repo, "HEAD")); + cl_git_pass(git_reset_default(_repo, _target, &_pathspecs)); + + assert_content_in_index(&_pathspecs, true, NULL); +} diff --git a/tests/stash/save.c b/tests/stash/save.c index f06c1fb71..87c6d7e0f 100644 --- a/tests/stash/save.c +++ b/tests/stash/save.c @@ -148,6 +148,25 @@ void test_stash_save__can_include_untracked_files(void) assert_blob_oid("refs/stash^3:just.ignore", NULL); } +void test_stash_save__untracked_skips_ignored(void) +{ + cl_git_append2file("stash/.gitignore", "bundle/vendor/\n"); + cl_must_pass(p_mkdir("stash/bundle", 0777)); + cl_must_pass(p_mkdir("stash/bundle/vendor", 0777)); + cl_git_mkfile("stash/bundle/vendor/blah", "contents\n"); + + cl_assert(git_path_exists("stash/when")); /* untracked */ + cl_assert(git_path_exists("stash/just.ignore")); /* ignored */ + cl_assert(git_path_exists("stash/bundle/vendor/blah")); /* ignored */ + + cl_git_pass(git_stash_save( + &stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED)); + + cl_assert(!git_path_exists("stash/when")); + cl_assert(git_path_exists("stash/bundle/vendor/blah")); + cl_assert(git_path_exists("stash/just.ignore")); +} + void test_stash_save__can_include_untracked_and_ignored_files(void) { cl_git_pass(git_stash_save(&stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED | GIT_STASH_INCLUDE_IGNORED)); @@ -342,7 +361,7 @@ void test_stash_save__can_stage_normal_then_stage_untracked(void) void test_stash_save__including_untracked_without_any_untracked_file_creates_an_empty_tree(void) { - cl_git_pass(p_unlink("stash/when")); + cl_must_pass(p_unlink("stash/when")); assert_status(repo, "what", GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED); assert_status(repo, "how", GIT_STATUS_INDEX_MODIFIED); @@ -354,3 +373,18 @@ void test_stash_save__including_untracked_without_any_untracked_file_creates_an_ assert_object_oid("stash^3^{tree}", EMPTY_TREE, GIT_OBJ_TREE); } + +void test_stash_save__skip_submodules(void) +{ + git_repository *untracked_repo; + cl_git_pass(git_repository_init(&untracked_repo, "stash/untracked_repo", false)); + cl_git_mkfile("stash/untracked_repo/content", "stuff"); + git_repository_free(untracked_repo); + + assert_status(repo, "untracked_repo/", GIT_STATUS_WT_NEW); + + cl_git_pass(git_stash_save( + &stash_tip_oid, repo, signature, NULL, GIT_STASH_INCLUDE_UNTRACKED)); + + assert_status(repo, "untracked_repo/", GIT_STATUS_WT_NEW); +} diff --git a/tests/stash/stash_helpers.c b/tests/stash/stash_helpers.c index 8b7d685f8..ff683eced 100644 --- a/tests/stash/stash_helpers.c +++ b/tests/stash/stash_helpers.c @@ -42,15 +42,11 @@ void assert_status( int status_flags) { unsigned int status; - int error; - error = git_status_file(&status, repo, path); - - if (status_flags < 0) { - cl_assert_equal_i(status_flags, error); - return; + if (status_flags < 0) + cl_assert_equal_i(status_flags, git_status_file(&status, repo, path)); + else { + cl_git_pass(git_status_file(&status, repo, path)); + cl_assert_equal_i((unsigned int)status_flags, status); } - - cl_assert_equal_i(0, error); - cl_assert_equal_i((unsigned int)status_flags, status); } diff --git a/tests/status/renames.c b/tests/status/renames.c index df5e23087..24b8aca2b 100644 --- a/tests/status/renames.c +++ b/tests/status/renames.c @@ -20,40 +20,36 @@ void test_status_renames__cleanup(void) cl_git_sandbox_cleanup(); } -static void rename_file(git_repository *repo, const char *oldname, const char *newname) +static void _rename_helper( + git_repository *repo, const char *from, const char *to, const char *extra) { git_buf oldpath = GIT_BUF_INIT, newpath = GIT_BUF_INIT; - git_buf_joinpath(&oldpath, git_repository_workdir(repo), oldname); - git_buf_joinpath(&newpath, git_repository_workdir(repo), newname); + cl_git_pass(git_buf_joinpath( + &oldpath, git_repository_workdir(repo), from)); + cl_git_pass(git_buf_joinpath( + &newpath, git_repository_workdir(repo), to)); cl_git_pass(p_rename(oldpath.ptr, newpath.ptr)); - git_buf_free(&oldpath); - git_buf_free(&newpath); -} - -static void rename_and_edit_file(git_repository *repo, const char *oldname, const char *newname) -{ - git_buf oldpath = GIT_BUF_INIT, newpath = GIT_BUF_INIT; - - git_buf_joinpath(&oldpath, git_repository_workdir(repo), oldname); - git_buf_joinpath(&newpath, git_repository_workdir(repo), newname); - - cl_git_pass(p_rename(oldpath.ptr, newpath.ptr)); - cl_git_append2file(newpath.ptr, "Added at the end to keep similarity!"); + if (extra) + cl_git_append2file(newpath.ptr, extra); git_buf_free(&oldpath); git_buf_free(&newpath); } +#define rename_file(R,O,N) _rename_helper((R), (O), (N), NULL) +#define rename_and_edit_file(R,O,N) \ + _rename_helper((R), (O), (N), "Added at the end to keep similarity!") + struct status_entry { git_status_t status; const char *oldname; const char *newname; }; -static void test_status( +static void check_status( git_status_list *status_list, struct status_entry *expected_list, size_t expected_len) @@ -61,9 +57,9 @@ static void test_status( const git_status_entry *actual; const struct status_entry *expected; const char *oldname, *newname; - size_t i; + size_t i, files_in_status = git_status_list_entrycount(status_list); - cl_assert_equal_sz(expected_len, git_status_list_entrycount(status_list)); + cl_assert_equal_sz(expected_len, files_in_status); for (i = 0; i < expected_len; i++) { actual = git_status_byindex(status_list, i); @@ -82,10 +78,12 @@ static void test_status( else cl_assert(expected->oldname == NULL); - if (newname) - cl_assert(git__strcmp(newname, expected->newname) == 0); - else - cl_assert(expected->newname == NULL); + if (actual->status & (GIT_STATUS_INDEX_RENAMED|GIT_STATUS_WT_RENAMED)) { + if (newname) + cl_assert(git__strcmp(newname, expected->newname) == 0); + else + cl_assert(expected->newname == NULL); + } } } @@ -109,7 +107,7 @@ void test_status_renames__head2index_one(void) cl_git_pass(git_index_write(index)); cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 1); + check_status(statuslist, expected, 1); git_status_list_free(statuslist); git_index_free(index); @@ -149,7 +147,7 @@ void test_status_renames__head2index_two(void) cl_git_pass(git_index_write(index)); cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 4); + check_status(statuslist, expected, 4); git_status_list_free(statuslist); git_index_free(index); @@ -178,7 +176,7 @@ void test_status_renames__head2index_no_rename_from_rewrite(void) cl_git_pass(git_index_write(index)); cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 2); + check_status(statuslist, expected, 2); git_status_list_free(statuslist); git_index_free(index); @@ -208,7 +206,7 @@ void test_status_renames__head2index_rename_from_rewrite(void) cl_git_pass(git_index_write(index)); cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 2); + check_status(statuslist, expected, 2); git_status_list_free(statuslist); git_index_free(index); @@ -228,7 +226,7 @@ void test_status_renames__index2workdir_one(void) rename_file(g_repo, "ikeepsix.txt", "newname.txt"); cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 1); + check_status(statuslist, expected, 1); git_status_list_free(statuslist); } @@ -254,7 +252,7 @@ void test_status_renames__index2workdir_two(void) rename_and_edit_file(g_repo, "untimely.txt", "bbb.txt"); cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 4); + check_status(statuslist, expected, 4); git_status_list_free(statuslist); } @@ -278,7 +276,7 @@ void test_status_renames__index2workdir_rename_from_rewrite(void) rename_file(g_repo, "_temp_.txt", "sixserving.txt"); cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 2); + check_status(statuslist, expected, 2); git_status_list_free(statuslist); git_index_free(index); @@ -309,7 +307,7 @@ void test_status_renames__both_one(void) rename_file(g_repo, "newname-index.txt", "newname-workdir.txt"); cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 1); + check_status(statuslist, expected, 1); git_status_list_free(statuslist); git_index_free(index); @@ -355,7 +353,7 @@ void test_status_renames__both_two(void) rename_file(g_repo, "untimely-index.txt", "untimely-both.txt"); cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 4); + check_status(statuslist, expected, 4); git_status_list_free(statuslist); git_index_free(index); @@ -399,7 +397,7 @@ void test_status_renames__both_rename_from_rewrite(void) rename_file(g_repo, "_temp_.txt", "sixserving.txt"); cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 3); + check_status(statuslist, expected, 3); git_status_list_free(statuslist); git_index_free(index); @@ -440,7 +438,7 @@ void test_status_renames__rewrites_only_for_renames(void) "This is enough content for the file to be rewritten.\n"); cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 1); + check_status(statuslist, expected, 1); git_status_list_free(statuslist); git_index_free(index); @@ -481,7 +479,7 @@ void test_status_renames__both_casechange_one(void) cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, (index_caps & GIT_INDEXCAP_IGNORE_CASE) ? + check_status(statuslist, (index_caps & GIT_INDEXCAP_IGNORE_CASE) ? expected_icase : expected_case, 1); git_status_list_free(statuslist); @@ -548,7 +546,7 @@ void test_status_renames__both_casechange_two(void) cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, (index_caps & GIT_INDEXCAP_IGNORE_CASE) ? + check_status(statuslist, (index_caps & GIT_INDEXCAP_IGNORE_CASE) ? expected_icase : expected_case, 4); git_status_list_free(statuslist); @@ -579,6 +577,135 @@ void test_status_renames__zero_byte_file_does_not_fail(void) cl_git_mkfile("renames/zerobyte.txt", ""); cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); - test_status(statuslist, expected, 2); + check_status(statuslist, expected, 2); + git_status_list_free(statuslist); +} + +#ifdef GIT_USE_ICONV +static char *nfc = "\xC3\x85\x73\x74\x72\xC3\xB6\x6D"; +static char *nfd = "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D"; +#endif + +void test_status_renames__precomposed_unicode_rename(void) +{ +#ifdef GIT_USE_ICONV + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected0[] = { + { GIT_STATUS_WT_NEW, nfd, NULL }, + { GIT_STATUS_WT_DELETED, "sixserving.txt", NULL }, + }; + struct status_entry expected1[] = { + { GIT_STATUS_WT_RENAMED, "sixserving.txt", nfd }, + }; + struct status_entry expected2[] = { + { GIT_STATUS_WT_DELETED, "sixserving.txt", NULL }, + { GIT_STATUS_WT_NEW, nfc, NULL }, + }; + struct status_entry expected3[] = { + { GIT_STATUS_WT_RENAMED, "sixserving.txt", nfc }, + }; + + rename_file(g_repo, "sixserving.txt", nfc); + + opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; + + cl_repo_set_bool(g_repo, "core.precomposeunicode", false); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + check_status(statuslist, expected0, ARRAY_SIZE(expected0)); + git_status_list_free(statuslist); + + opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + check_status(statuslist, expected1, ARRAY_SIZE(expected1)); + git_status_list_free(statuslist); + + cl_repo_set_bool(g_repo, "core.precomposeunicode", true); + + opts.flags &= ~GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + check_status(statuslist, expected2, ARRAY_SIZE(expected2)); + git_status_list_free(statuslist); + + opts.flags |= GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + check_status(statuslist, expected3, ARRAY_SIZE(expected3)); git_status_list_free(statuslist); +#endif } + +void test_status_renames__precomposed_unicode_toggle_is_rename(void) +{ +#ifdef GIT_USE_ICONV + git_status_list *statuslist; + git_status_options opts = GIT_STATUS_OPTIONS_INIT; + struct status_entry expected0[] = { + { GIT_STATUS_INDEX_RENAMED, "ikeepsix.txt", nfd }, + }; + struct status_entry expected1[] = { + { GIT_STATUS_WT_RENAMED, nfd, nfc }, + }; + struct status_entry expected2[] = { + { GIT_STATUS_INDEX_RENAMED, nfd, nfc }, + }; + struct status_entry expected3[] = { + { GIT_STATUS_INDEX_RENAMED | GIT_STATUS_WT_RENAMED, nfd, nfd }, + }; + + cl_repo_set_bool(g_repo, "core.precomposeunicode", false); + rename_file(g_repo, "ikeepsix.txt", nfd); + + { + git_index *index; + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_remove_bypath(index, "ikeepsix.txt")); + cl_git_pass(git_index_add_bypath(index, nfd)); + cl_git_pass(git_index_write(index)); + git_index_free(index); + } + + opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED | + GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX | + GIT_STATUS_OPT_RENAMES_INDEX_TO_WORKDIR; + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + check_status(statuslist, expected0, ARRAY_SIZE(expected0)); + git_status_list_free(statuslist); + + cl_repo_commit_from_index(NULL, g_repo, NULL, 0, "commit nfd"); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + cl_assert_equal_sz(0, git_status_list_entrycount(statuslist)); + git_status_list_free(statuslist); + + cl_repo_set_bool(g_repo, "core.precomposeunicode", true); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + check_status(statuslist, expected1, ARRAY_SIZE(expected1)); + git_status_list_free(statuslist); + + { + git_index *index; + cl_git_pass(git_repository_index(&index, g_repo)); + cl_git_pass(git_index_remove_bypath(index, nfd)); + cl_git_pass(git_index_add_bypath(index, nfc)); + cl_git_pass(git_index_write(index)); + git_index_free(index); + } + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + check_status(statuslist, expected2, ARRAY_SIZE(expected2)); + git_status_list_free(statuslist); + + cl_repo_set_bool(g_repo, "core.precomposeunicode", false); + + cl_git_pass(git_status_list_new(&statuslist, g_repo, &opts)); + check_status(statuslist, expected3, ARRAY_SIZE(expected3)); + git_status_list_free(statuslist); +#endif +} + |