diff options
Diffstat (limited to 'tests/merge/workdir/dirty.c')
-rw-r--r-- | tests/merge/workdir/dirty.c | 352 |
1 files changed, 0 insertions, 352 deletions
diff --git a/tests/merge/workdir/dirty.c b/tests/merge/workdir/dirty.c deleted file mode 100644 index 6044bca43..000000000 --- a/tests/merge/workdir/dirty.c +++ /dev/null @@ -1,352 +0,0 @@ -#include "clar_libgit2.h" -#include "git2/merge.h" -#include "buffer.h" -#include "merge.h" -#include "index.h" -#include "../merge_helpers.h" -#include "posix.h" - -#define TEST_REPO_PATH "merge-resolve" -#define MERGE_BRANCH_OID "7cb63eed597130ba4abb87b3e544b85021905520" - -#define AUTOMERGEABLE_MERGED_FILE \ - "this file is changed in master\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is automergeable\n" \ - "this file is changed in branch\n" - -#define CHANGED_IN_BRANCH_FILE \ - "changed in branch\n" - -static git_repository *repo; -static git_index *repo_index; - -static char *unaffected[][4] = { - { "added-in-master.txt", NULL }, - { "changed-in-master.txt", NULL }, - { "unchanged.txt", NULL }, - { "added-in-master.txt", "changed-in-master.txt", NULL }, - { "added-in-master.txt", "unchanged.txt", NULL }, - { "changed-in-master.txt", "unchanged.txt", NULL }, - { "added-in-master.txt", "changed-in-master.txt", "unchanged.txt", NULL }, - { "new_file.txt", NULL }, - { "new_file.txt", "unchanged.txt", NULL }, - { NULL }, -}; - -static char *affected[][5] = { - { "automergeable.txt", NULL }, - { "changed-in-branch.txt", NULL }, - { "conflicting.txt", NULL }, - { "removed-in-branch.txt", NULL }, - { "automergeable.txt", "changed-in-branch.txt", NULL }, - { "automergeable.txt", "conflicting.txt", NULL }, - { "automergeable.txt", "removed-in-branch.txt", NULL }, - { "changed-in-branch.txt", "conflicting.txt", NULL }, - { "changed-in-branch.txt", "removed-in-branch.txt", NULL }, - { "conflicting.txt", "removed-in-branch.txt", NULL }, - { "automergeable.txt", "changed-in-branch.txt", "conflicting.txt", NULL }, - { "automergeable.txt", "changed-in-branch.txt", "removed-in-branch.txt", NULL }, - { "automergeable.txt", "conflicting.txt", "removed-in-branch.txt", NULL }, - { "changed-in-branch.txt", "conflicting.txt", "removed-in-branch.txt", NULL }, - { "automergeable.txt", "changed-in-branch.txt", "conflicting.txt", "removed-in-branch.txt", NULL }, - { NULL }, -}; - -static char *result_contents[4][6] = { - { "automergeable.txt", AUTOMERGEABLE_MERGED_FILE, NULL, NULL }, - { "changed-in-branch.txt", CHANGED_IN_BRANCH_FILE, NULL, NULL }, - { "automergeable.txt", AUTOMERGEABLE_MERGED_FILE, "changed-in-branch.txt", CHANGED_IN_BRANCH_FILE, NULL, NULL }, - { NULL } -}; - -void test_merge_workdir_dirty__initialize(void) -{ - repo = cl_git_sandbox_init(TEST_REPO_PATH); - git_repository_index(&repo_index, repo); -} - -void test_merge_workdir_dirty__cleanup(void) -{ - git_index_free(repo_index); - cl_git_sandbox_cleanup(); -} - -static void set_core_autocrlf_to(git_repository *repo, bool value) -{ - git_config *cfg; - - cl_git_pass(git_repository_config(&cfg, repo)); - cl_git_pass(git_config_set_bool(cfg, "core.autocrlf", value)); - - git_config_free(cfg); -} - -static int merge_branch(void) -{ - git_oid their_oids[1]; - git_annotated_commit *their_head; - git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT; - git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; - int error; - - cl_git_pass(git_oid_fromstr(&their_oids[0], MERGE_BRANCH_OID)); - cl_git_pass(git_annotated_commit_lookup(&their_head, repo, &their_oids[0])); - - checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; - error = git_merge(repo, (const git_annotated_commit **)&their_head, 1, &merge_opts, &checkout_opts); - - git_annotated_commit_free(their_head); - - return error; -} - -static void write_files(char *files[]) -{ - char *filename; - git_buf path = GIT_BUF_INIT, content = GIT_BUF_INIT; - size_t i; - - for (i = 0, filename = files[i]; filename; filename = files[++i]) { - git_buf_clear(&path); - git_buf_clear(&content); - - git_buf_printf(&path, "%s/%s", TEST_REPO_PATH, filename); - git_buf_printf(&content, "This is a dirty file in the working directory!\n\n" - "It will not be staged! Its filename is %s.\n", filename); - - cl_git_mkfile(path.ptr, content.ptr); - } - - git_buf_dispose(&path); - git_buf_dispose(&content); -} - -static void hack_index(char *files[]) -{ - char *filename; - struct stat statbuf; - git_buf path = GIT_BUF_INIT; - git_index_entry *entry; - struct p_timeval times[2]; - time_t now; - size_t i; - - /* Update the index to suggest that checkout placed these files on - * disk, keeping the object id but updating the cache, which will - * emulate a Git implementation's different filter. - * - * We set the file's timestamp to before now to pretend that - * it was an old checkout so we don't trigger the racy - * protections would would check the content. - */ - - now = time(NULL); - times[0].tv_sec = now - 5; - times[0].tv_usec = 0; - times[1].tv_sec = now - 5; - times[1].tv_usec = 0; - - for (i = 0, filename = files[i]; filename; filename = files[++i]) { - git_buf_clear(&path); - - cl_assert(entry = (git_index_entry *) - git_index_get_bypath(repo_index, filename, 0)); - - cl_git_pass(git_buf_printf(&path, "%s/%s", TEST_REPO_PATH, filename)); - cl_git_pass(p_utimes(path.ptr, times)); - cl_git_pass(p_stat(path.ptr, &statbuf)); - - entry->ctime.seconds = (int32_t)statbuf.st_ctime; - entry->mtime.seconds = (int32_t)statbuf.st_mtime; -#if defined(GIT_USE_NSEC) - entry->ctime.nanoseconds = statbuf.st_ctime_nsec; - entry->mtime.nanoseconds = statbuf.st_mtime_nsec; -#else - entry->ctime.nanoseconds = 0; - entry->mtime.nanoseconds = 0; -#endif - entry->dev = statbuf.st_dev; - entry->ino = statbuf.st_ino; - entry->uid = statbuf.st_uid; - entry->gid = statbuf.st_gid; - entry->file_size = (uint32_t)statbuf.st_size; - } - - git_buf_dispose(&path); -} - -static void stage_random_files(char *files[]) -{ - char *filename; - size_t i; - - write_files(files); - - for (i = 0, filename = files[i]; filename; filename = files[++i]) - cl_git_pass(git_index_add_bypath(repo_index, filename)); -} - -static void stage_content(char *content[]) -{ - git_reference *head; - git_object *head_object; - git_buf path = GIT_BUF_INIT; - char *filename, *text; - size_t i; - - cl_git_pass(git_repository_head(&head, repo)); - cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJECT_COMMIT)); - cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD, NULL)); - - for (i = 0, filename = content[i], text = content[++i]; - filename && text; - filename = content[++i], text = content[++i]) { - - git_buf_clear(&path); - - cl_git_pass(git_buf_printf(&path, "%s/%s", TEST_REPO_PATH, filename)); - - cl_git_mkfile(path.ptr, text); - cl_git_pass(git_index_add_bypath(repo_index, filename)); - } - - git_object_free(head_object); - git_reference_free(head); - git_buf_dispose(&path); -} - -static int merge_dirty_files(char *dirty_files[]) -{ - git_reference *head; - git_object *head_object; - int error; - - cl_git_pass(git_repository_head(&head, repo)); - cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJECT_COMMIT)); - cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD, NULL)); - - write_files(dirty_files); - - error = merge_branch(); - - git_object_free(head_object); - git_reference_free(head); - - return error; -} - -static int merge_differently_filtered_files(char *files[]) -{ - git_reference *head; - git_object *head_object; - int error; - - cl_git_pass(git_repository_head(&head, repo)); - cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJECT_COMMIT)); - cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD, NULL)); - - /* Emulate checkout with a broken or misconfigured filter: modify some - * files on-disk and then update the index with the updated file size - * and time, as if some filter applied them. These files should not be - * treated as dirty since we created them. - * - * (Make sure to update the index stamp to defeat racy-git protections - * trying to sanity check the files in the index; those would rehash the - * files, showing them as dirty, the exact mechanism we're trying to avoid.) - */ - - write_files(files); - hack_index(files); - - cl_git_pass(git_index_write(repo_index)); - - error = merge_branch(); - - git_object_free(head_object); - git_reference_free(head); - - return error; -} - -static int merge_staged_files(char *staged_files[]) -{ - stage_random_files(staged_files); - return merge_branch(); -} - -void test_merge_workdir_dirty__unaffected_dirty_files_allowed(void) -{ - char **files; - size_t i; - - for (i = 0, files = unaffected[i]; files[0]; files = unaffected[++i]) - 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_OBJECT_COMMIT)); - cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD, 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; - size_t i; - - for (i = 0, files = affected[i]; files[0]; files = affected[++i]) - cl_git_fail(merge_dirty_files(files)); -} - -void test_merge_workdir_dirty__staged_files_in_index_disallowed(void) -{ - char **files; - size_t i; - - for (i = 0, files = unaffected[i]; files[0]; files = unaffected[++i]) - cl_git_fail(merge_staged_files(files)); - - for (i = 0, files = affected[i]; files[0]; files = affected[++i]) - cl_git_fail(merge_staged_files(files)); -} - -void test_merge_workdir_dirty__identical_staged_files_allowed(void) -{ - char **content; - size_t i; - - set_core_autocrlf_to(repo, false); - - for (i = 0, content = result_contents[i]; content[0]; content = result_contents[++i]) { - stage_content(content); - - cl_git_pass(git_index_write(repo_index)); - cl_git_pass(merge_branch()); - } -} - -void test_merge_workdir_dirty__honors_cache(void) -{ - char **files; - size_t i; - - for (i = 0, files = affected[i]; files[0]; files = affected[++i]) - cl_git_pass(merge_differently_filtered_files(files)); -} |